diff options
author | levine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1996-10-21 21:41:34 +0000 |
---|---|---|
committer | levine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1996-10-21 21:41:34 +0000 |
commit | a5fdebc5f6375078ec1763850a4ca23ec7fe6458 (patch) | |
tree | bcf0a25c3d45a209a6e3ac37b233a4812f29c732 /ace | |
download | ATCD-a5fdebc5f6375078ec1763850a4ca23ec7fe6458.tar.gz |
Initial revision
Diffstat (limited to 'ace')
453 files changed, 85982 insertions, 0 deletions
diff --git a/ace/ACE.cpp b/ace/ACE.cpp new file mode 100644 index 00000000000..3ce0ec93ccc --- /dev/null +++ b/ace/ACE.cpp @@ -0,0 +1,738 @@ +// ACE.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/IPC_SAP.h" +#include "ace/Time_Value.h" +#include "ace/Handle_Set.h" +#include "ace/ACE.h" +#include "ace/Thread_Manager.h" +#include "ace/Reactor.h" + +int +ACE::register_stdin_handler (ACE_Event_Handler *eh, + ACE_Reactor *reactor, + ACE_Thread_Manager *thr_mgr, + int flags) +{ +#if defined (ACE_WIN32) + return thr_mgr->spawn (&ACE::read_adapter, eh, flags); +#else + return reactor->register_handler (ACE_STDIN, eh, ACE_Event_Handler::READ_MASK); +#endif /* ACE_WIN32 */ +} + +// Used to read from non-socket ACE_HANDLEs in our own thread to work +// around Win32 limitations that don't allow us to select() on +// non-sockets (such as ACE_STDIN). This is commonly used in +// situations where the Reactor is used to demultiplex read events on +// ACE_STDIN on UNIX. Note that <event_handler> must be a subclass of +// <ACE_Event_Handler>. If the <get_handle> method of this event +// handler returns <ACE_INVALID_HANDLE> we default to reading from +// ACE_STDIN. + +void * +ACE::read_adapter (void *t) +{ + ACE_Event_Handler *this_ptr = (ACE_Event_Handler *) t; + ACE_HANDLE handle = this_ptr->get_handle (); + + if (handle == ACE_INVALID_HANDLE) + handle = ACE_STDIN; + + while (this_ptr->handle_input (handle) != -1) + continue; + + this_ptr->handle_close (handle, ACE_Event_Handler::READ_MASK); + return 0; +} + +const char * +ACE::execname (const char *old_name) +{ +#if defined (ACE_HAS_WIN32) + if (ACE_OS::strstr (old_name, ".exe") == 0) + { + char *new_name; + + ACE_NEW_RETURN (new_name, char[ACE_OS::strlen (old_name) + + ACE_OS::strlen (".exe") + + 1], -1); + char *end = new_name; + end = ACE::strecpy (new_name, old_name); + // Concatenate the .exe suffix onto the end of the executable. + ACE_OS::strcpy (end, ".exe"); + return new_name; + } +#endif /* ACE_HAS_WIN32 */ + return old_name; +} + +u_long +ACE::hash_pjw (const char *str) +{ + u_long hash = 0; + + for (const char *temp = str; *temp != 0; temp++) + { + hash = (hash << 4) + (*temp * 13); + + u_long g = hash & 0xf0000000; + + if (g) + { + hash ^= (g >> 24); + hash ^= g; + } + } + + return hash; +} + +char * +ACE::strenvdup (const char *str) +{ + ACE_TRACE ("ACE::strenvdup"); + + char *temp; + + if (str[0] == '$' + && (temp = ACE_OS::getenv (&str[1])) != 0) + return ACE_OS::strdup (temp); + else + return ACE_OS::strdup (str); +} + +int +ACE::ldfind (const char *filename, + char *pathname, + size_t maxlen) +{ + ACE_TRACE ("ACE::ldfind"); + if (ACE_OS::strchr (filename, ACE_DIRECTORY_SEPARATOR_CHAR) != 0) + { + // Use absolute pathname. + ACE_OS::strncpy (pathname, filename, maxlen); + return 0; + } + else + { + // Using LD_LIBRARY_PATH + char *ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH); + + if (ld_path != 0 && (ld_path = ACE_OS::strdup (ld_path)) != 0) + { + // Look at each dynamic lib directory in the search path. + char *path_entry = ACE_OS::strtok (ld_path, + ACE_LD_SEARCH_PATH_SEPARATOR_STR); + + int result = 0; + + while (path_entry != 0) + { + if (ACE_OS::strlen (path_entry) + 1 + ACE_OS::strlen (filename) >= maxlen) + { + errno = ENOMEM; + result = -1; + break; + } + ACE_OS::sprintf (pathname, "%s%c%s", + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + filename); + + if (ACE_OS::access (pathname, R_OK) == 0) + break; + path_entry = ACE_OS::strtok (0, ACE_LD_SEARCH_PATH_SEPARATOR_STR); + } + + ACE_OS::free ((void *) ld_path); + return result; + } + } + + errno = ENOENT; + return -1; +} + +FILE * +ACE::ldopen (const char *filename, const char *type) +{ + ACE_TRACE ("ACE::ldopen"); + char buf[MAXPATHLEN]; + + if (ACE::ldfind (filename, buf, sizeof buf) == -1) + return 0; + else + return ACE_OS::fopen (buf, type); +} + +const char * +ACE::basename (const char *pathname, char delim) +{ + ACE_TRACE ("ACE::basename"); + const char *temp = ::strrchr (pathname, delim); + + if (temp == 0) + return pathname; + else + return temp + 1; +} + +// Miscellaneous static methods used throughout ACE. + +ssize_t +ACE::send_n (ACE_HANDLE handle, const void *buf, size_t len) +{ + ACE_TRACE ("ACE::send_n"); + size_t bytes_written; + int n; + + for (bytes_written = 0; bytes_written < len; bytes_written += n) + if ((n = ACE::send (handle, (const char *) buf + bytes_written, + len - bytes_written)) == -1) + return -1; + + return bytes_written; +} + +ssize_t +ACE::send_n (ACE_HANDLE handle, const void *buf, size_t len, int flags) +{ + ACE_TRACE ("ACE::send_n"); + size_t bytes_written; + int n; + + for (bytes_written = 0; bytes_written < len; bytes_written += n) + if ((n = ACE_OS::send (handle, (const char *) buf + bytes_written, + len - bytes_written, flags)) == -1) + return -1; + + return bytes_written; +} + +ssize_t +ACE::recv_n (ACE_HANDLE handle, void *buf, size_t len) +{ + ACE_TRACE ("ACE::recv_n"); + size_t bytes_read; + int n; + + for (bytes_read = 0; bytes_read < len; bytes_read += n) + if ((n = ACE::recv (handle, (char *) buf + bytes_read, + len - bytes_read)) == -1) + return -1; + else if (n == 0) + break; + + return bytes_read; +} + +ssize_t +ACE::recv_n (ACE_HANDLE handle, void *buf, size_t len, int flags) +{ + ACE_TRACE ("ACE::recv_n"); + size_t bytes_read; + int n; + + for (bytes_read = 0; bytes_read < len; bytes_read += n) + if ((n = ACE_OS::recv (handle, (char *) buf + bytes_read, + len - bytes_read, flags)) == -1) + return -1; + else if (n == 0) + break; + + return bytes_read; +} + + // Receive <len> bytes into <buf> from <handle> (uses the <read> + // system call on UNIX and the <ReadFile> call on Win32). +ssize_t +ACE::read_n (ACE_HANDLE handle, + void *buf, + size_t len) +{ + ACE_TRACE ("ACE::read_n"); + + size_t bytes_read; + int n; + + for (bytes_read = 0; bytes_read < len; bytes_read += n) + if ((n = ACE_OS::read (handle, (char *) buf + bytes_read, + len - bytes_read)) == -1) + return -1; + else if (n == 0) + break; + + return bytes_read; +} + +// Receive <len> bytes into <buf> from <handle> (uses the <write> +// system call on UNIX and the <WriteFile> call on Win32). + +ssize_t +ACE::write_n (ACE_HANDLE handle, + const void *buf, + size_t len) +{ + ACE_TRACE ("ACE::write_n"); + + size_t bytes_written; + int n; + + for (bytes_written = 0; bytes_written < len; bytes_written += n) + if ((n = ACE_OS::write (handle, (const char *) buf + bytes_written, + len - bytes_written)) == -1) + return -1; + + return bytes_written; +} + +// Format buffer into printable format. This is useful for debugging. +// Portions taken from mdump by J.P. Knight (J.P.Knight@lut.ac.uk) +// Modifications by Todd Montgomery. + +int +ACE::format_hexdump (char *buffer, int size, char *obuf, int obuf_sz) +{ + ACE_TRACE ("ACE::format_hexdump"); + + u_char c; + char textver[16 + 1]; + + int maxlen = (obuf_sz / 68) * 16; + + if (size > maxlen) + size = maxlen; + + int i; + + for (i = 0; i < (size >> 4); i++) + { + int j; + + for (j = 0 ; j < 16; j++) + { + c = buffer[(i << 4) + j]; + ::sprintf (obuf, "%02x ", c); + obuf += 3; + if (j == 7) + { + ::sprintf (obuf, " "); + obuf++; + } + textver[j] = (c < 0x20 || c > 0x7e) ? '.' : c; + } + + textver[j] = 0; + + ::sprintf (obuf, " %s\n", textver); + + while (*obuf != '\0') + obuf++; + } + + if (size % 16) + { + for (i = 0 ; i < size % 16; i++) + { + c = buffer[size - size % 16 + i]; + ::sprintf (obuf,"%02x ",c); + obuf += 3; + if (i == 7) + { + ::sprintf (obuf, " "); + obuf++; + } + textver[i] = (c < 0x20 || c > 0x7e) ? '.' : c; + } + + for (i = size % 16; i < 16; i++) + { + ::sprintf (obuf, " "); + obuf += 3; + textver[i] = ' '; + } + + textver[i] = 0; + ::sprintf (obuf, " %s\n", textver); + } + return size; +} + +// Returns the current timestamp in the form +// "hour:minute:second:microsecond." The month, day, and year are +// also stored in the beginning of the date_and_time array. Returns 0 +// if unsuccessful, else returns pointer to beginning of the "time" +// portion of <day_and_time>. + +char * +ACE::timestamp (char date_and_time[], int date_and_timelen) +{ + ACE_TRACE ("ACE::timestamp"); + + if (date_and_timelen < 35) + { + errno = EINVAL; + return 0; + } + +#if defined (WIN32) + // @@ Jesper, I think Win32 supports all the UNIX versions below. + // Therefore, we can probably remove this WIN32 ifdef altogether. + SYSTEMTIME local; + ::GetLocalTime (&local); + + ACE_OS::sprintf (date_and_time, "%02d/%02d/%04d%02d.%02d.%02d.%06d", + (int) local.wMonth, // new, also the %02d in sprintf + (int) local.wDay, // new, also the %02d in sprintf + (int) local.wYear, // new, also the %02d in sprintf + (int) local.wHour, + (int) local.wMinute, + (int) local.wSecond, + (int) local.wMilliseconds * 1000); +#else // UNIX + char timebuf[26]; // This magic number is based on the ctime(3c) man page. + ACE_Time_Value cur_time = ACE_OS::gettimeofday (); + time_t secs = cur_time.sec (); + ACE_OS::ctime_r (&secs, timebuf, sizeof timebuf); + ACE_OS::strncpy (date_and_time, timebuf, date_and_timelen); + ACE_OS::sprintf (&date_and_time[19], ".%06d", cur_time.usec ()); +#endif /* WIN32 */ + date_and_time[26] = '\0'; + return &date_and_time[11]; +} + +// This function rounds the request to a multiple of the page size. + +size_t +ACE::round_to_pagesize (off_t len) +{ + ACE_TRACE ("ACE::round_to_pagesize"); + return (len + (ACE_PAGE_SIZE - 1)) & ~(ACE_PAGE_SIZE - 1); +} + +ACE_HANDLE +ACE::handle_timed_complete (ACE_HANDLE h, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE::handle_timed_complete"); + ACE_Handle_Set rd_handles; + ACE_Handle_Set wr_handles; + + rd_handles.set_bit (h); + wr_handles.set_bit (h); + + int n = ACE_OS::select (int (h) + 1, + rd_handles, + wr_handles, + 0, timeout); + // If we failed to connect within the time period allocated by the + // caller, then we fail (e.g., the remote host might have been too + // busy to accept our call). + if (n <= 0) + { + if (n == 0) + errno = ETIMEDOUT; + return ACE_INVALID_HANDLE; + } + // Check if the handle is ready for reading and the handle is *not* + // ready for writing, which may indicate a problem. But we need to + // make sure... +#if defined (ACE_HAS_TLI) + else if (rd_handles.is_set (h) && !wr_handles.is_set (h)) +#else + else if (rd_handles.is_set (h)) +#endif /* ACE_HAS_TLI */ + { + char dummy; + // The following recv() won't block provided that the + // ACE_NONBLOCK flag has not been turned off . + + n = ACE::recv (h, &dummy, 1, MSG_PEEK); + if (n <= 0) + { + if (n == 0) + errno = ECONNREFUSED; + return ACE_INVALID_HANDLE; + } + } + + // 1. The HANDLE is ready for writing or 2. recv() returned that + // there are data to be read, which indicates the connection was + // successfully established. + return h; +} + +ACE_HANDLE +ACE::handle_timed_open (ACE_Time_Value *timeout, + LPCTSTR name, + int flags, + int perms) +{ + ACE_TRACE ("ACE::handle_timed_open"); + + if (timeout != 0) + { + // Open the named pipe or file using non-blocking mode... + ACE_HANDLE handle = ACE_OS::open (name, + flags | ACE_NONBLOCK, + 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); +} + +// Wait up to <timeout> amount of time to accept a connection. + +int +ACE::handle_timed_accept (ACE_HANDLE listener, + ACE_Time_Value *timeout, + int restart) +{ + ACE_TRACE ("ACE::handle_timed_accept"); + // Make sure we don't bomb out on erroneous values. + if (listener == ACE_INVALID_HANDLE) + return -1; + + // Use the select() implementation rather than poll(). + ACE_Handle_Set rd_handle; + rd_handle.set_bit (listener); + + // We need a loop here if <restart> is enabled. + + for (;;) + { + switch (ACE_OS::select (int (listener) + 1, + rd_handle, 0, 0, + timeout)) + { + case -1: + if (errno == EINTR && restart) + continue; + else + return -1; + /* NOTREACHED */ + case 0: + if (timeout != 0 && timeout->sec() == 0 && timeout->usec() == 0) + errno = EWOULDBLOCK; + else + errno = ETIMEDOUT; + return -1; + /* NOTREACHED */ + case 1: + return 0; + /* NOTREACHED */ + default: + errno = EINVAL; + return -1; + /* NOTREACHED */ + } + } + /* NOTREACHED */ + return 0; +} + +// Bind socket to an unused port. + +int +ACE::bind_port (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE::bind_port"); + sockaddr_in sin; + const int MAX_SHORT = 65535; + static int upper_limit = MAX_SHORT; + int lower_limit = IPPORT_RESERVED; + int round_trip = upper_limit; + + ACE_OS::memset ((void *) &sin, 0, sizeof sin); + sin.sin_family = AF_INET; +#if defined (ACE_HAS_SIN_LEN) + sin.sin_family = sizeof sin; +#endif /* ACE_HAS_SIN_LEN */ + sin.sin_addr.s_addr = INADDR_ANY; + + for (;;) + { + sin.sin_port = htons (upper_limit); + + if (ACE_OS::bind (handle, (sockaddr *) &sin, sizeof sin) >= 0) + return 0; + else if (errno != EADDRINUSE) + return -1; + else + { + upper_limit--; + + /* Wrap back around when we reach the bottom. */ + if (upper_limit <= lower_limit) + upper_limit = MAX_SHORT; + + /* See if we have already gone around once! */ + if (upper_limit == round_trip) + { + errno = EAGAIN; + return -1; + } + } + } +} + +// Make the current process a UNIX daemon. This is based on Stevens +// code from APUE. + +int +ACE::daemonize (void) +{ + ACE_TRACE ("ACE::daemonize"); +#if !defined (ACE_WIN32) + pid_t pid; + + if ((pid = ACE_OS::fork ()) == -1) + return -1; + else if (pid != 0) + ACE_OS::exit (0); /* parent exits */ + + /* child continues */ + ACE_OS::setsid (); /* become session leader */ + + ACE_OS::chdir ("/"); /* change working directory */ + + ACE_OS::umask (0); /* clear our file mode creation mask */ + return 0; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE::max_handles (void) +{ + ACE_TRACE ("ACE::set_handle_limit"); +#if defined (_SC_OPEN_MAX) + return ACE_OS::sysconf (_SC_OPEN_MAX); +#elif defined (RLIMIT_NOFILE) + rlimit rl; + ACE_OS::getrlimit (RLIMIT_NOFILE, &rl); + rl.rlim_cur; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +// Set the number of currently open handles in the process. +// +// If NEW_LIMIT == -1 set the limit to the maximum allowable. +// Otherwise, set it to be the value of NEW_LIMIT. + +int +ACE::set_handle_limit (int new_limit) +{ + ACE_TRACE ("ACE::set_handle_limit"); +#if defined (RLIMIT_NOFILE) + struct rlimit rl; + + int max_handles = ACE::max_handles (); + + if (new_limit < 0 || new_limit > max_handles) + rl.rlim_cur = max_handles; + else + rl.rlim_cur = new_limit; + + return ACE_OS::setrlimit (RLIMIT_NOFILE, &rl); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +// Flags are file status flags to turn on. + +int +ACE::set_flags (ACE_HANDLE handle, int flags) +{ + ACE_TRACE ("ACE::set_fl"); +#if defined (ACE_WIN32) + switch (flags) + { + case ACE_NONBLOCK: + // nonblocking argument (1) + // blocking: (0) + { + u_long nonblock = 1; + return ACE_OS::ioctl (handle, FIONBIO, &nonblock); + } + default: + errno = ENOTSUP; + return -1; + } +#else + int val; + + if ((val = ACE_OS::fcntl (handle, F_GETFL, 0)) == -1) + return -1; + + val |= flags; /* turn on flags */ + + if (ACE_OS::fcntl (handle, F_SETFL, val) == -1) + return -1; + else + return 0; +#endif /* ACE_WIN32 */ +} + +// Flags are the file status flags to turn off. + +int +ACE::clr_flags (ACE_HANDLE handle, int flags) +{ + ACE_TRACE ("ACE::clr_fl"); + +#if defined (ACE_WIN32) + switch (flags) + { + case ACE_NONBLOCK: + // nonblocking argument (1) + // blocking: (0) + { + u_long nonblock = 0; + return ACE_OS::ioctl (handle, FIONBIO, &nonblock); + } + default: + errno = ENOTSUP; + return -1; + } +#else + int val; + + if ((val = ACE_OS::fcntl (handle, F_GETFL, 0)) == -1) + return -1; + + val &= ~flags; /* turn flags off */ + + if (ACE_OS::fcntl (handle, F_SETFL, val) == -1) + return -1; + else + return 0; +#endif /* ACE_WIN32 */ +} + +int +ACE::map_errno (int error) +{ + switch (error) + { +#if defined (ACE_WIN32) + case WSAEWOULDBLOCK: + return EAGAIN; // Same as UNIX errno EWOULDBLOCK. +#endif /* ACE_WIN32 */ + } + + return error; +} diff --git a/ace/ACE.h b/ace/ACE.h new file mode 100644 index 00000000000..36536b0a57d --- /dev/null +++ b/ace/ACE.h @@ -0,0 +1,237 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_ACE_H) +#define ACE_ACE_H + +#include "ace/OS.h" + +// Forward declarations. +class ACE_Time_Value; +class ACE_Thread_Manager; +class ACE_Reactor; +class ACE_Event_Handler; + +class ACE_Export ACE +{ + // = TITLE + // Contains value added ACE methods that extend the behavior + // of the UNIX and Win32 OS calls. + // + // = DESCRIPTION + // This class consolidates all these ACE static methods in a + // single place in order to manage the namespace better. These + // methods are put here rather than in ACE_OS in order to + // separate concerns. +public: + // = Network I/O functions that factor out differences between Win32 + // and UNIX. + static ssize_t recv (ACE_HANDLE handle, + void *buf, + size_t len, + int flags); + // Receive up to <len> bytes into <buf> from <handle> (uses the + // <recv> call). + + static ssize_t recv (ACE_HANDLE handle, + void *buf, + size_t len); + // Receive up to <len> bytes into <buf> from <handle> (uses the + // <read> system call on UNIX and the <recv> call on Win32). + + static ssize_t send (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags); + // Send up to <len> bytes into <buf> from <handle> (uses the <send> + // call). + + static ssize_t send (ACE_HANDLE handle, + const void *buf, + size_t len); + // Send up to <len> bytes into <buf> from <handle> (uses the <write> + // system call on UNIX and the <send> call on Win32). + + // = Network I/O functions that recv and send exactly n bytes. + static ssize_t recv_n (ACE_HANDLE handle, + void *buf, + size_t len, + int flags); + // Receive <len> bytes into <buf> from <handle> (uses the <recv> + // call). + + static ssize_t recv_n (ACE_HANDLE handle, + void *buf, + size_t len); + // Receive <len> bytes into <buf> from <handle> (uses the <read> + // system call on UNIX and the <recv> call on Win32). + + static ssize_t send_n (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags); + // Receive <len> bytes into <buf> from <handle> (uses the <send> + // system call). + + static ssize_t send_n (ACE_HANDLE handle, + const void *buf, + size_t len); + // Receive <len> bytes into <buf> from <handle> (uses the <write> + // system call on UNIX and the <recv> call on Win32). + + // = File system I/O functions that encapsulate differences between + // UNIX and Win32 and also send and recv exactly n bytes. + static ssize_t read_n (ACE_HANDLE handle, + void *buf, + size_t len); + // Receive <len> bytes into <buf> from <handle> (uses the <read> + // system call on UNIX and the <ReadFile> call on Win32). + + static ssize_t write_n (ACE_HANDLE handle, + const void *buf, + size_t len); + // Receive <len> bytes into <buf> from <handle> (uses the <write> + // system call on UNIX and the <WriteFile> call on Win32). + + // = Functions that perform useful behavior related to establishing + // socket connections active and passively. + static int bind_port (ACE_HANDLE handle); + // Bind a new unused port to <handle>. + + static int handle_timed_accept (ACE_HANDLE listener, + ACE_Time_Value *timeout, + int restart); + // Wait up to <timeout> amount of time to passively establish a + // connection. This method doesn't perform the <accept>, it just + // does the timed wait... + + static ACE_HANDLE handle_timed_complete (ACE_HANDLE listener, + ACE_Time_Value *timeout); + // Wait up to <timeout> amount of time to complete an actively + // established non-blocking connection. + + // = Operations on HANDLEs. + + static ACE_HANDLE handle_timed_open (ACE_Time_Value *timeout, + LPCTSTR name, + int flags, + int perms); + // Wait up to <timeout> amount of time to actively open a device. + // This method doesn't perform the <connect>, it just does the timed + // wait... + + static int set_flags (ACE_HANDLE handle, + int flags); + // Set flags associated with <handle>. + + static int clr_flags (ACE_HANDLE handle, + int flags); + // Clear flags associated with <handle>. + + static int set_handle_limit (int new_limit = -1); + // Reset the limit on the number of open handles. If <new_limit> == + // -1 set the limit to the maximum allowable. Otherwise, set it to + // be the value of <new_limit>. + + static int max_handles (void); + // Returns the maximum number of open handles currently permitted in + // this process. This maximum may be extended using + // <ACE::set_handle_limit>. + + // = Miscelleous functions. + static size_t round_to_pagesize (off_t length); + // Rounds the request to a multiple of the page size. + + static int format_hexdump (char *buffer, int size, char *obuf, int obuf_sz); + // Format buffer into printable format. This is useful for + // debugging. + + static char *strenvdup (const char *str); + // Return a dynamically allocated duplicate of <str>, substituting + // the environment variable if <str[0] == '$'>. Note that the + // pointer is allocated with <ACE_OS::malloc> and must be freed by + // <ACE_OS::free> + + static char *strecpy (char *s, const char *t); + // Copies <t> to <s>, returning a pointer to the end of the copied + // region (rather than the beginning, a la <strcpy>. + + static const char *execname (const char *pathname); + // On Win32 returns <pathname> if it already ends in ".exe," + // otherwise returns a dynamically allocated buffer containing + // "<pathname>.exe". Always returns <pathname> on UNIX. + + static const char *basename (const char *pathname, char delim); + // Returns the "basename" of a <pathname>. + + static char *timestamp (char date_and_time[], int time_len); + // Returns the current timestamp in the form + // "hour:minute:second:microsecond." The month, day, and year are + // also stored in the beginning of the date_and_time array. Returns + // 0 if unsuccessful, else returns pointer to beginning of the + // "time" portion of <day_and_time>. + + static int daemonize (void); + // Become a daemon process. + + // = Methods for searching and opening shared libraries using + // relative naming. + static int ldfind (const char *filename, + char *pathname, + size_t maxlen); + // Finds the file <filename> either using absolute path or using + // ACE_LD_SEARCH_PATH (e.g., $LD_LIBRARY_PATH on UNIX or $PATH on + // Win32). + + static FILE *ldopen (const char *filename, const char *type); + // Uses <ldopen> to locate and open the appropriate <filename> and + // returns a pointer to the file, else it returns a NULL + // pointer. <type> specifies how the file should be open. + + static u_long hash_pjw (const char *str); + // Computes the hash value of <str> using the ``Hash PJW'' routine... + + static int map_errno (int error); + // Map troublesome win32 errno values to values that standard C + // strerr function understands. Thank you Microsoft. + + static void *read_adapter (void *event_handler); + // Used to read from non-socket ACE_HANDLEs in our own thread to + // work around Win32 limitations that don't allow us to select() on + // non-sockets (such as ACE_STDIN). This is commonly used in + // situations where the Reactor is used to demultiplex read events + // on ACE_STDIN on UNIX. Note that <event_handler> must be a + // subclass of <ACE_Event_Handler>. If the <get_handle> method of + // this event handler returns <ACE_INVALID_HANDLE> we default to + // reading from ACE_STDIN. + + static int register_stdin_handler (ACE_Event_Handler *eh, + ACE_Reactor *reactor, + ACE_Thread_Manager *thr_mgr, + int flags = THR_DETACHED); + // Abstracts away from the differences between Win32 and ACE with + // respect to reading from ACE_STDIN (which is non-select()'able on + // Win32. + +private: + ACE (void); + // Ensure we can't define an instance of this class... +}; + +#include "ace/ACE.i" + +#endif /* ACE_ACE_H */ diff --git a/ace/ACE.i b/ace/ACE.i new file mode 100644 index 00000000000..c8467a5cde9 --- /dev/null +++ b/ace/ACE.i @@ -0,0 +1,61 @@ +/* -*- C++ -*- */ +// $Id$ + +// ACE.i +#include "ace/Log_Msg.h" + +// Miscellaneous static methods used throughout ACE. + +inline ssize_t +ACE::send (ACE_HANDLE handle, const void *buf, size_t len) +{ + ACE_TRACE ("ACE::send"); + +#if defined (ACE_WIN32) + return ACE_OS::send (handle, (const char *) buf, len); +#elif defined (VXWORKS) + return ::write (handle, (char *) buf, len); +#else + return ::write (handle, (const char *) buf, len); +#endif /* ACE_WIN32 */ +} + +inline ssize_t +ACE::send (ACE_HANDLE handle, const void *buf, size_t len, int flags) +{ + ACE_TRACE ("ACE::send"); + return ACE_OS::send (handle, (const char *) buf, len, flags); +} + +inline ssize_t +ACE::recv (ACE_HANDLE handle, void *buf, size_t len) +{ + ACE_TRACE ("ACE::recv"); +#if defined (ACE_WIN32) + return ACE_OS::recv (handle, (char *) buf, len); +#else + return ACE_OS::read (handle, (char *) buf, len); +#endif /* ACE_WIN32 */ +} + +inline ssize_t +ACE::recv (ACE_HANDLE handle, void *buf, size_t len, int flags) +{ + ACE_TRACE ("ACE::recv"); + + return ACE_OS::recv (handle, (char *) buf, len, flags); +} + +inline char * +ACE::strecpy (char *s, const char *t) +{ + ACE_TRACE ("ACE::strecpy"); + register char *dscan = s; + register const char *sscan = t; + + while ((*dscan++ = *sscan++) != '\0') + continue; + + return dscan - 1; +} + diff --git a/ace/ARGV.cpp b/ace/ARGV.cpp new file mode 100644 index 00000000000..2c54a2e9c25 --- /dev/null +++ b/ace/ARGV.cpp @@ -0,0 +1,202 @@ +// ARGV.cpp +// $Id$ + +// Transforms a string BUF into an ARGV-style vector of strings. + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/ARGV.h" + +#if !defined (__ACE_INLINE__) +#include "ace/ARGV.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_ARGV) + +void +ACE_ARGV::dump (void) const +{ + ACE_TRACE ("ACE_ARGV::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "argc_ = %d", this->argc_)); + + for (size_t i = 0; i < this->argc_; i++) + ACE_DEBUG ((LM_DEBUG, "\nargv_[%i] = %s", i, this->argv_[i])); + + ACE_DEBUG ((LM_DEBUG, "\nbuf = %s\n")); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ARGV::ACE_ARGV (char buf[], + int substitute_env_args) + : argv_ (0), + argc_ (0), + buf_ (0) +{ + ACE_TRACE ("ACE_ARGV::ACE_ARGV"); + + if (buf == 0) + return; + + char *cp = buf; + + // First pass: count arguments. + + // '#' is the start-comment token.. + while (*cp != '\0' && *cp != '#') + { + // Skip whitespace.. + while (isspace (*cp)) + cp++; + + // Increment count and move to next whitespace.. + if (*cp != '\0') + this->argc_++; + + // Grok quotes.... + if (*cp == '\'' || *cp == '"') + { + char quote = *cp; + + // Scan past the string.. + for (cp++; *cp != '\0' && *cp != quote; cp++) + continue; + + // '\0' implies unmatched quote.. + if (*cp == '\0') + { + ACE_ERROR ((LM_ERROR, + "unmatched %c detected\n", quote)); + this->argc_--; + break; + } + else + cp++; + } + else // Skip over non-whitespace.... + while (*cp != '\0' && !isspace (*cp)) + cp++; + } + + // Second pass: copy arguments.. + char arg[BUFSIZ]; + + // Make a new argv vector of argc + 1 elements. + ACE_NEW (this->argv_, char *[this->argc_ + 1]); + + for (size_t i = 0; i < this->argc_; i++) + { + // Skip whitespace.. + while (isspace (*buf)) + buf++; + + // Copy next argument and move to next whitespace.. + if (*buf == '\'' || *buf == '"') + { + char quote = *buf++; + + for (cp = arg; + *buf != '\0' && *buf != quote; + buf++, cp++) + if (cp - arg < sizeof arg) + *cp = *buf; + + *cp = '\0'; + if (*buf == quote) + buf++; + } + else + { + for (cp = arg; + *buf && !isspace (*buf); + buf++, cp++) + if (cp - arg < sizeof arg) + *cp = *buf; + *cp = '\0'; + } + + // Check for environment variable substitution here. + if (substitute_env_args) + this->argv_[i] = ACE::strenvdup (arg); + else + this->argv_[i] = ACE_OS::strdup (arg); + } + + this->argv_[this->argc_] = 0; +} + +ACE_ARGV::ACE_ARGV (char *argv[], + int substitute_env_args) + : argv_ (0), + argc_ (0), + buf_ (0) +{ + ACE_TRACE ("ACE_ARGV::ACE_ARGV"); + + if (argv == 0 || argv[0] == 0) + return; + + int buf_len = 0; + + // Determine the length of the buffer. + + for (int i = 0; argv[i] != 0; i++) + { + char *temp; + + // 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 + 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 (this->buf_, char[buf_len]); + + char *end = this->buf_; + + for (int j = 0; argv[j] != 0; j++) + { + char *temp; + + // Account for environment variables. + if (substitute_env_args + && (argv[j][0] == '$' + && (temp = ACE_OS::getenv (&argv[j][1])) != 0)) + end = ACE::strecpy (end, temp); + else + end = ACE::strecpy (end, argv[j]); + + // Add white space and advance the pointer. + *end++ = ' '; + } + + // Null terminate the string. + *end = '\0'; +} + +// Free up the space allocated by the constructor.. + +ACE_ARGV::~ACE_ARGV (void) +{ + ACE_TRACE ("ACE_ARGV::~ACE_ARGV"); + if (this->argv_ == 0) + return; + + for (int i = 0; this->argv_[i] != 0; i++) + ACE_OS::free ((void *) this->argv_[i]); + + ACE_OS::free ((void *) this->argv_); + delete this->buf_; +} + diff --git a/ace/ARGV.h b/ace/ARGV.h new file mode 100644 index 00000000000..75f087a5155 --- /dev/null +++ b/ace/ARGV.h @@ -0,0 +1,80 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ARGV.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_ARGUMENT_VECTOR_H) +#define ACE_ARGUMENT_VECTOR_H + +#include "ace/ACE.h" + +class ACE_Export ACE_ARGV + // = TITLE + // Transforms a string <buf> into an <argv> style vector of + // strings or an <argv> style vector of string <buf>, performing + // environment variable substitutions if necessary. +{ +public: + // = Initialization and termination. + ACE_ARGV (char buf[], int substitute_env_args = 1); + // Converts <buf> into an <argv>-style vector of strings. If + // <substitute_env_args> is enabled then we'll substitute the + // environment variables for each $ENV encountered in the string. + + ACE_ARGV (char *argv[], int substitute_env_args = 1); + // Converts <argv> into a linear string. If <substitute_env_args> + // is enabled then we'll substitute the environment variables for + // each $ENV encountered in the string. + + ~ACE_ARGV (void); + // Destructor. + + // = Accessor arguments. + char *operator[] (int index) const; + // Returns the <index>th string in the ARGV array. + + char **argv (void) const; + // Returns the <argv> array. Caller should not delete this memory + // since the <ARGV> destructor will delete it. + + size_t argc (void) const; + // Returns <argc>. + + char *buf (void) const; + // Returns the <buf>. Caller should not delete this memory since + // the <ARGV> destructor will delete it. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + size_t argc_; + // Number of arguments in the ARGV array. + + char **argv_; + // The array of string arguments. + + char *buf_; + // Buffer containing the <argv> contents. +}; + +#if defined (__ACE_INLINE__) +#include "ace/ARGV.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_ARGUMENT_VECTOR_H */ diff --git a/ace/ARGV.i b/ace/ARGV.i new file mode 100644 index 00000000000..5bb9d242252 --- /dev/null +++ b/ace/ARGV.i @@ -0,0 +1,32 @@ +/* -*- C++ -*- */ +// $Id$ + +// ARGV.i + +ACE_INLINE size_t +ACE_ARGV::argc (void) const +{ + ACE_TRACE ("ACE_ARGV::argc"); + return this->argc_; +} + +ACE_INLINE char * +ACE_ARGV::buf (void) const +{ + ACE_TRACE ("ACE_ARGV::buf"); + return this->buf_; +} + +ACE_INLINE char * +ACE_ARGV::operator[] (int i) const +{ + ACE_TRACE ("ACE_ARGV::operator[]"); + return this->argv_[i]; +} + +ACE_INLINE char ** +ACE_ARGV::argv (void) const +{ + ACE_TRACE ("ACE_ARGV::argv"); + return this->argv_; +} diff --git a/ace/Acceptor.cpp b/ace/Acceptor.cpp new file mode 100644 index 00000000000..d6994d0e957 --- /dev/null +++ b/ace/Acceptor.cpp @@ -0,0 +1,969 @@ +// Acceptor.cpp +// $Id$ + +#if !defined (ACE_ACCEPTOR_C) +#define ACE_ACCEPTOR_C + +#define ACE_BUILD_DLL +#include "ace/ACE.h" +#include "ace/Acceptor.h" + +// Shorthand names. +#define SH SVC_HANDLER +#define PR_AC_1 ACE_PEER_ACCEPTOR_1 +#define PR_AC_2 ACE_PEER_ACCEPTOR_2 +#define PR_AD ACE_PEER_ACCEPTOR_ADDR + +ACE_ALLOC_HOOK_DEFINE(ACE_Acceptor) + +template <class SH, PR_AC_1> void +ACE_Acceptor<SH, PR_AC_2>::dump (void) const +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "reactor_ = %x", this->reactor_)); + this->peer_acceptor_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SH, PR_AC_1> +ACE_Acceptor<SH, PR_AC_2>::operator ACE_PEER_ACCEPTOR & () const +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::operator ACE_PEER_ACCEPTOR &"); + return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; +} + +template <class SH, PR_AC_1> ACE_Reactor * +ACE_Acceptor<SH, PR_AC_2>::reactor (void) const +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::reactor"); + return this->reactor_; +} + +template <class SH, PR_AC_1> void +ACE_Acceptor<SH, PR_AC_2>::reactor (ACE_Reactor *r) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::reactor"); + this->reactor_ = r; +} + +template <class SH, PR_AC_1> ACE_PEER_ACCEPTOR & +ACE_Acceptor<SH, PR_AC_2>::acceptor (void) const +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::acceptor"); + return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; +} + +// Returns ACE_HANDLE of the underlying Acceptor_Strategy. + +template <class SH, PR_AC_1> ACE_HANDLE +ACE_Acceptor<SH, PR_AC_2>::get_handle (void) const +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::get_handle"); + return this->peer_acceptor_.get_handle (); +} + +// Initialize the appropriate strategies for creation, passive +// connection acceptance, and concurrency, and then register <this> +// with the Reactor and listen for connection requests at the +// designated <local_addr>. + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::open (const PR_AD &local_addr, + ACE_Reactor *reactor) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::open"); + this->reactor_ = reactor; + + // Must supply a valid Reactor to Acceptor::open()... + + if (reactor == 0) + { + errno = EINVAL; + return -1; + } + + if (this->peer_acceptor_.open (local_addr, 1) == -1) + return -1; + + return this->reactor_->register_handler + (this, ACE_Event_Handler::READ_MASK); +} + +// Simple constructor. + +template <class SH, PR_AC_1> +ACE_Acceptor<SH, PR_AC_2>::ACE_Acceptor (ACE_Reactor *reactor) + : reactor_ (reactor) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::ACE_Acceptor"); +} + +template <class SH, PR_AC_1> +ACE_Acceptor<SH, PR_AC_2>::ACE_Acceptor (const PR_AD &addr, + ACE_Reactor *reactor) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::ACE_Acceptor"); + if (this->open (addr, reactor) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Acceptor::ACE_Acceptor")); +} + +template <class SH, PR_AC_1> +ACE_Acceptor<SH, PR_AC_2>::~ACE_Acceptor (void) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::~ACE_Acceptor"); + this->handle_close (); +} + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::fini (void) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::fini"); + return ACE_Acceptor<SH, PR_AC_2>::handle_close (); +} + +// Hook called by the explicit dynamic linking facility. + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::init"); + return -1; +} + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::info (char **strp, size_t length) const +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::info"); + char buf[BUFSIZ]; + char addr_str[BUFSIZ]; + PR_AD addr; + + if (this->acceptor ().get_local_addr (addr) == -1) + return -1; + else if (addr.addr_to_string (addr_str, sizeof addr) == -1) + return -1; + + ACE_OS::sprintf (buf, "%s\t %s %s", + "ACE_Acceptor", addr_str, "# acceptor factory\n"); + + if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, buf, length); + return ACE_OS::strlen (buf); +} + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::suspend (void) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::suspend"); + return this->reactor_->suspend_handler (this); +} + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::resume (void) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::resume"); + return this->reactor_->resume_handler (this); +} + +// Perform termination activities when <this> is removed from the +// <reactor_>. + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::handle_close (ACE_HANDLE, + ACE_Reactor_Mask) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::handle_close"); + // Guard against multiple closes. + if (this->reactor_ != 0) + { + ACE_HANDLE handle = this->get_handle (); + + // We must use the <handle> obtained *before* we deleted the + // accept_strategy_... + + this->reactor_->remove_handler + (handle, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + + this->reactor_ = 0; + } + return 0; +} + +// Bridge method for creating a SVC_HANDLER. The strategy for +// creating a SVC_HANDLER are configured into the Acceptor via it's +// <creation_strategy_>. The default is to create a new SVC_HANDLER. +// However, subclasses can override this strategy to perform +// SVC_HANDLER creation in any way that they like (such as creating +// subclass instances of SVC_HANDLER, using a singleton, dynamically +// linking the handler, etc.). + +template <class SH, PR_AC_1> SH * +ACE_Acceptor<SH, PR_AC_2>::make_svc_handler (void) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::make_svc_handler"); + return new SH; +} + +// Bridge method for accepting the new connection into the +// <svc_handler>. The default behavior delegates to the +// PEER_ACCEPTOR::accept() in the Acceptor_Strategy. + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::accept_svc_handler (SH *svc_handler) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::accept_svc_handler"); + if (this->peer_acceptor_.accept (*svc_handler) == -1) + { + // Close down handler to avoid memory leaks. + svc_handler->close (0); + return -1; + } + else + return 0; +} + +// Bridge method for activating a <svc_handler> with the appropriate +// concurrency strategy. The default behavior of this method is to +// activate the SVC_HANDLER by calling its open() method (which allows +// the SVC_HANDLER to define its own concurrency strategy). However, +// subclasses can override this strategy to do more sophisticated +// concurrency activations (such as creating the SVC_HANDLER as an +// "active object" via multi-threading or multi-processing). + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::activate_svc_handler (SH *svc_handler) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::activate_svc_handler"); + if (svc_handler->open ((void *) this) == -1) + { + svc_handler->close (0); + return -1; + } + else + return 0; +} + +// Template Method that makes a SVC_HANDLER (using the appropriate +// creation strategy), accept the connection into the SVC_HANDLER, and +// then activate the SVC_HANDLER. + +template <class SH, PR_AC_1> int +ACE_Acceptor<SH, PR_AC_2>::handle_input (ACE_HANDLE listener) +{ + ACE_TRACE ("ACE_Acceptor<SH, PR_AC_2>::handle_input"); + ACE_Handle_Set conn_handle; + + // Default is "timeout (0, 0)," which means "poll." + ACE_Time_Value timeout; + + // Accept connections from clients (note that a loop is used for two + // reasons: + // + // 1. It allows us to accept all pending connections without an + // extra trip through the ACE_Reactor and without having to use + // non-blocking I/O... + // + // 2. It allows the TLI_SAP::ACE_Acceptor class to work correctly (don't + // ask -- TLI is *horrible*...)). + + // @@ What should we do if any of the substrategies fail? Right + // now, we just log an error message and return 0 (which means that + // the Acceptor remains registered with the Reactor)... + do + { + // Create a service handler, using the appropriate creation + // strategy. + + SH *svc_handler = this->make_svc_handler (); + + if (svc_handler == 0) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "make_svc_handler"), 0); + + // Accept connection into the Svc_Handler. + + else if (this->accept_svc_handler (svc_handler) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "accept_svc_handler"), 0); + + // Activate the <svc_handler> using the designated concurrency + // strategy (note that this method becomes responsible for + // handling errors and freeing up the memory if things go + // awry...). + + else if (this->activate_svc_handler (svc_handler) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "activate_svc_handler"), 0); + + conn_handle.set_bit (listener); + } + // Now, check to see if there is another connection pending and + // break out of the loop if there is none. + while (ACE_OS::select (int (listener) + 1, conn_handle, 0, 0, &timeout) == 1); + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Strategy_Acceptor) + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::suspend (void) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::suspend"); + + // First suspend the SVC_HANDLER's we've created. + if (this->scheduling_strategy_->suspend () == -1) + return -1; + else // Then suspend ourselves. + return ACE_Acceptor<SH, PR_AC_2>::suspend (); +} + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::resume (void) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::resume"); + + // First resume ourselves. + if (ACE_Acceptor<SH, PR_AC_2>::suspend () == -1) + return -1; + else // Then resume the SVC_HANDLER's we've created. + return this->scheduling_strategy_->resume (); +} + +template <class SH, PR_AC_1> void +ACE_Strategy_Acceptor<SH, PR_AC_2>::dump (void) const +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_Acceptor<SH, PR_AC_2>::dump (); + this->creation_strategy_->dump (); + ACE_DEBUG ((LM_DEBUG, "delete_creation_strategy_ = %d", delete_creation_strategy_)); + this->accept_strategy_->dump (); + ACE_DEBUG ((LM_DEBUG, "delete_accept_strategy_ = %d", delete_accept_strategy_)); + this->concurrency_strategy_->dump (); + ACE_DEBUG ((LM_DEBUG, "delete_concurrency_strategy_ = %d", delete_concurrency_strategy_)); + this->scheduling_strategy_->dump (); + ACE_DEBUG ((LM_DEBUG, "delete_scheduling_strategy_ = %d", delete_scheduling_strategy_)); + ACE_DEBUG ((LM_DEBUG, "\nservice_name_ = %s", this->service_name_)); + ACE_DEBUG ((LM_DEBUG, "\nservice_description_ = %s", this->service_description_)); + ACE_DEBUG ((LM_DEBUG, "\nservice_port_ = %d", this->service_port_)); + this->service_addr_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SH, PR_AC_1> ACE_PEER_ACCEPTOR & +ACE_Strategy_Acceptor<SH, PR_AC_2>::acceptor (void) const +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::acceptor"); + return this->accept_strategy_->acceptor (); +} + +template <class SH, PR_AC_1> +ACE_Strategy_Acceptor<SH, PR_AC_2>::operator ACE_PEER_ACCEPTOR & () const +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::operator ACE_PEER_ACCEPTOR &"); + return this->accept_strategy_->acceptor (); +} + +// Returns ACE_HANDLE of the underlying Acceptor_Strategy. + +template <class SH, PR_AC_1> ACE_HANDLE +ACE_Strategy_Acceptor<SH, PR_AC_2>::get_handle (void) const +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::get_handle"); + return this->accept_strategy_->get_handle (); +} + +// Initialize the appropriate strategies for creation, passive +// connection acceptance, and concurrency, and then register <this> +// with the Reactor and listen for connection requests at the +// designated <local_addr>. + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::open (const PR_AD &local_addr, + ACE_Reactor *reactor, + ACE_Creation_Strategy<SH> *cre_s, + ACE_Accept_Strategy<SH, PR_AC_2> *acc_s, + ACE_Concurrency_Strategy<SH> *con_s, + ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s, + const char service_name[], + const char service_description[]) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::open"); + + if (this->service_name_ == 0 && service_name != 0) + this->service_name_ = ACE_OS::strdup (service_name); + if (this->service_description_ == 0 && service_description != 0) + this->service_description_ = ACE_OS::strdup (service_description); + + this->reactor (reactor); + + // Must supply a valid Reactor to Acceptor::open()... + if (reactor == 0) + { + errno = EINVAL; + return -1; + } + + // Initialize the creation strategy. + + if (cre_s == 0) + { + ACE_NEW_RETURN (cre_s, CREATION_STRATEGY, -1); + this->delete_creation_strategy_ = 1; + } + this->creation_strategy_ = cre_s; + + // Initialize the accept strategy. + + if (acc_s == 0) + { + ACE_NEW_RETURN (acc_s, ACCEPT_STRATEGY, -1); + this->delete_accept_strategy_ = 1; + } + this->accept_strategy_ = acc_s; + + if (this->accept_strategy_->open (local_addr, 1) == -1) + return -1; + + // Initialize the concurrency strategy. + + if (con_s == 0) + { + ACE_NEW_RETURN (con_s, CONCURRENCY_STRATEGY, -1); + this->delete_concurrency_strategy_ = 1; + } + this->concurrency_strategy_ = con_s; + + // Initialize the scheduling strategy. + + if (sch_s == 0) + { + ACE_NEW_RETURN (sch_s, SCHEDULING_STRATEGY, -1); + this->delete_scheduling_strategy_ = 1; + } + this->scheduling_strategy_ = sch_s; + + return this->reactor ()->register_handler (this, + ACE_Event_Handler::READ_MASK); +} + +// Simple constructor. + +template <class SH, PR_AC_1> +ACE_Strategy_Acceptor<SH, PR_AC_2>::ACE_Strategy_Acceptor (const char service_name[], + const char service_description[]) + : creation_strategy_ (0), + accept_strategy_ (0), + concurrency_strategy_ (0), + scheduling_strategy_ (0), + delete_creation_strategy_ (0), + delete_accept_strategy_ (0), + delete_concurrency_strategy_ (0), + delete_scheduling_strategy_ (0), + service_name_ (0), + service_description_ (0) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::ACE_Strategy_Acceptor"); + + if (service_name != 0) + this->service_name_ = ACE_OS::strdup (service_name); + if (service_description != 0) + this->service_description_ = ACE_OS::strdup (service_description); +} + +template <class SH, PR_AC_1> +ACE_Strategy_Acceptor<SH, PR_AC_2>::ACE_Strategy_Acceptor (const PR_AD &addr, + ACE_Reactor *reactor, + ACE_Creation_Strategy<SH> *cre_s, + ACE_Accept_Strategy<SH, PR_AC_2> *acc_s, + ACE_Concurrency_Strategy<SH> *con_s, + ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s, + const char service_name[], + const char service_description[]) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::ACE_Strategy_Acceptor"); + if (this->open (addr, reactor, cre_s, acc_s, con_s, sch_s, + service_name, service_description) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Strategy_Acceptor::ACE_Strategy_Acceptor")); +} + +// Perform termination activities when <this> is removed from the +// <ACE_Reactor>. + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::handle_close (ACE_HANDLE, + ACE_Reactor_Mask) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::handle_close"); + // Guard against multiple closes. + if (this->creation_strategy_ != 0) + { + ACE_HANDLE handle = this->get_handle (); + + if (this->delete_creation_strategy_) + delete this->creation_strategy_; + this->delete_creation_strategy_ = 0; + this->creation_strategy_ = 0; + + if (this->delete_accept_strategy_) + delete this->accept_strategy_; + this->delete_accept_strategy_ = 0; + this->accept_strategy_ = 0; + + if (this->delete_concurrency_strategy_) + delete this->concurrency_strategy_; + this->delete_concurrency_strategy_ = 0; + this->concurrency_strategy_ = 0; + + if (this->delete_scheduling_strategy_) + delete this->scheduling_strategy_; + this->delete_scheduling_strategy_ = 0; + this->scheduling_strategy_ = 0; + + // We must use the <handle> obtained *before* we deleted the + // accept_strategy_... + + this->reactor ()->remove_handler + (handle, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + + this->reactor (0); + } + return 0; +} + +// Bridge method for creating a SVC_HANDLER. The strategy for +// creating a SVC_HANDLER are configured into the Acceptor via it's +// <creation_strategy_>. The default is to create a new SVC_HANDLER. +// However, subclasses can override this strategy to perform +// SVC_HANDLER creation in any way that they like (such as creating +// subclass instances of SVC_HANDLER, using a singleton, dynamically +// linking the handler, etc.). + +template <class SH, PR_AC_1> SH * +ACE_Strategy_Acceptor<SH, PR_AC_2>::make_svc_handler (void) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::make_svc_handler"); + return this->creation_strategy_->make_svc_handler (); +} + +// Bridge method for accepting the new connection into the +// <svc_handler>. The default behavior delegates to the +// <Strategy_Acceptor::accept> in the Acceptor_Strategy. + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::accept_svc_handler (SH *svc_handler) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::accept_svc_handler"); + return this->accept_strategy_->accept_svc_handler (svc_handler); +} + +// Bridge method for activating a <svc_handler> with the appropriate +// concurrency strategy. The default behavior of this method is to +// activate the SVC_HANDLER by calling its open() method (which allows +// the SVC_HANDLER to define its own concurrency strategy). However, +// subclasses can override this strategy to do more sophisticated +// concurrency activations (such as creating the SVC_HANDLER as an +// "active object" via multi-threading or multi-processing). + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::activate_svc_handler (SH *svc_handler) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::activate_svc_handler"); + return this->concurrency_strategy_->activate_svc_handler + (svc_handler, (void *) this); +} + +template <class SH, PR_AC_1> +ACE_Strategy_Acceptor<SH, PR_AC_2>::~ACE_Strategy_Acceptor (void) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::~ACE_Strategy_Acceptor"); + ACE_OS::free ((void *) this->service_name_); + ACE_OS::free ((void *) this->service_description_); + this->handle_close (); +} + +// Signal the server to shutdown gracefully. + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::handle_signal (int, siginfo_t *, ucontext_t *) +{ + ACE_TRACE ("ACE_Strategy_Acceptor::handle_signal"); + ACE_Service_Config::end_reactor_event_loop (); + return 0; +} + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::info (char **strp, + size_t length) const +{ + ACE_TRACE ("ACE_Strategy_Acceptor::info"); + char buf[BUFSIZ]; + char service_addr_str[BUFSIZ]; + PR_AD addr; + + if (this->acceptor ().get_local_addr (addr) == -1) + return -1; + else if (addr.addr_to_string (service_addr_str, sizeof addr) == -1) + return -1; + + // @@ Should add the protocol in... + ACE_OS::sprintf (buf, "%s\t %s #%s\n", + this->service_name_, + service_addr_str, + this->service_description_); + + if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, buf, length); + return ACE_OS::strlen (buf); +} + +template <class SH, PR_AC_1> int +ACE_Strategy_Acceptor<SH, PR_AC_2>::fini (void) +{ + ACE_TRACE ("ACE_Strategy_Acceptor<SH, PR_AC_2>::fini"); + return this->ACE_Strategy_Acceptor<SH, PR_AC_2>::handle_close (); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Oneshot_Acceptor) + +template <class SH, PR_AC_1> void +ACE_Oneshot_Acceptor<SH, PR_AC_2>::dump (void) const +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "reactor_ = %x", this->reactor_)); + ACE_DEBUG ((LM_DEBUG, "\nsvc_handler_ = %x", this->svc_handler_)); + ACE_DEBUG ((LM_DEBUG, "\nrestart_ = %d", this->restart_)); + this->peer_acceptor_.dump (); + ACE_DEBUG ((LM_DEBUG, "delete_concurrency_strategy_ = %d", + delete_concurrency_strategy_)); + this->concurrency_strategy_->dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::open (const PR_AD &addr, + ACE_Reactor *reactor, + ACE_Concurrency_Strategy<SH> *con_s) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::open"); + this->reactor (reactor); + + // Initialize the concurrency strategy. + + if (con_s == 0) + { + ACE_NEW_RETURN (con_s, ACE_Concurrency_Strategy<SH>, -1); + this->delete_concurrency_strategy_ = 1; + } + this->concurrency_strategy_ = con_s; + + // Reuse the addr, even if it is already in use...! + return this->peer_acceptor_.open (addr, 1); +} + +template <class SH, PR_AC_1> +ACE_Oneshot_Acceptor<SH, PR_AC_2>::ACE_Oneshot_Acceptor (void) + : delete_concurrency_strategy_ (0), + reactor_ (0) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::ACE_Oneshot_Acceptor"); +} + +template <class SH, PR_AC_1> +ACE_Oneshot_Acceptor<SH, PR_AC_2>::ACE_Oneshot_Acceptor (const PR_AD &addr, + ACE_Reactor *reactor, + ACE_Concurrency_Strategy<SH> *cs) + : delete_concurrency_strategy_ (0) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::ACE_Oneshot_Acceptor"); + if (this->open (addr, reactor, cs) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor")); +} + +template <class SH, PR_AC_1> +ACE_Oneshot_Acceptor<SH, PR_AC_2>::~ACE_Oneshot_Acceptor (void) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::~ACE_Oneshot_Acceptor"); + this->handle_close (); +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::handle_close (ACE_HANDLE, + ACE_Reactor_Mask) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::handle_close"); + // Guard against multiple closes. + if (this->concurrency_strategy_ != 0) + { + if (this->delete_concurrency_strategy_) + delete this->concurrency_strategy_; + this->delete_concurrency_strategy_ = 0; + this->concurrency_strategy_ = 0; + + // Note that if we aren't actually registered with the + // ACE_Reactor then it's ok for this call to fail... + + this->reactor_ && this->reactor_->remove_handler (this, + ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + + this->reactor_ = 0; + + if (this->peer_acceptor_.close () == -1) + ACE_ERROR ((LM_ERROR, "close\n")); + } + return 0; +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::handle_timeout"); + errno = ETIMEDOUT; + this->svc_handler_->handle_timeout (tv, arg); + + // Since we aren't necessarily registered with the Reactor, don't + // bother to check the return value here... + this->reactor_ && this->reactor_->remove_handler + (this, ACE_Event_Handler::READ_MASK); + return 0; +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::cancel (void) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::cancel"); + return this->reactor_ && this->reactor_->cancel_timer (this); +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::register_handler (SH *svc_handler, + const ACE_Synch_Options &synch_options, + int restart) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::register_handler"); + // Can't do this if we don't have a Reactor. + if (this->reactor_ == 0) + return -1; + else + { + this->svc_handler_ = svc_handler; + this->restart_ = restart; + ACE_Time_Value *tv = (ACE_Time_Value *) synch_options.time_value (); + + if (tv != 0 + && this->reactor_->schedule_timer (this, synch_options.arg (), + *tv) == 0) + return -1; + else + return this->reactor_->register_handler (this, + ACE_Event_Handler::READ_MASK); + } +} + +// Bridge method for activating a <svc_handler> with the appropriate +// concurrency strategy. The default behavior of this method is to +// activate the SVC_HANDLER by calling its open() method (which allows +// the SVC_HANDLER to define its own concurrency strategy). However, +// subclasses can override this strategy to do more sophisticated +// concurrency activations (such as creating the SVC_HANDLER as an +// "active object" via multi-threading or multi-processing). + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::activate_svc_handler (SH *svc_handler) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::activate_svc_handler"); + return this->concurrency_strategy_->activate_svc_handler + (svc_handler, (void *) this); +} + +// Factors out the code shared between the <accept> and <handle_input> +// methods. + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::shared_accept (SH *svc_handler, + PR_AD *remote_addr, + ACE_Time_Value *timeout, + int restart) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::shared_accept"); + if (svc_handler == 0) + return -1; + + // Accept connection into the Svc_Handler. + else if (this->peer_acceptor_.accept (*svc_handler, remote_addr, + timeout, restart) == -1) + { + // Check whether we just timed out or whether we failed... + if (!(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + // Close down handler to avoid memory leaks. + svc_handler->close (0); + return -1; + } + // Activate the <svc_handler> using the designated concurrency + // strategy (note that this method becomes responsible for + // handling errors and freeing up the memory if things go + // awry...) + else + return this->activate_svc_handler (svc_handler); +} + +// Make a SVC_HANDLER, accept the connection into the SVC_HANDLER, and +// then activate the SVC_HANDLER. Note that SVC_HANDLER::open() +// decides what type of concurrency strategy to use. + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::accept (SH *svc_handler, + PR_AD *remote_addr, + const ACE_Synch_Options &synch_options, + int restart) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::accept"); + // Note that if timeout == ACE_Time_Value (x, y) where (x > 0 || y > + // 0) then this->connector_.connect() will block synchronously. If + // <use_reactor> is set then we don't want this to happen (since we + // want the ACE_Reactor to do the timeout asynchronously). + // Therefore, we'll force this->connector_ to use ACE_Time_Value (0, + // 0) in this case... + + ACE_Time_Value *timeout; + int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR]; + + if (use_reactor) + timeout = (ACE_Time_Value *) &ACE_Time_Value::zero; + else + timeout = (ACE_Time_Value *) synch_options.time_value (); + + if (this->shared_accept (svc_handler, remote_addr, timeout, restart) == -1) + { + if (use_reactor && errno == EWOULDBLOCK) + // We couldn't accept right away, so let's wait in the ACE_Reactor. + this->register_handler (svc_handler, synch_options, restart); + return -1; + } + return 0; +} + +// Accepts one pending connection from a client (since we're the +// "oneshot" Acceptor). + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::handle_input (ACE_HANDLE listener) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::handle_input"); + int result = 0; + + // Cancel any timer that might be pending. + this->cancel (); + + if (this->shared_accept (this->svc_handler_, 0, 0, this->restart_) == -1) + result = -1; + if (this->reactor_ && this->reactor_->remove_handler + (this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL) == -1) + result = -1; + return result; +} + +// Hook called by the explicit dynamic linking facility. + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::init"); + return -1; +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::fini (void) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::fini"); + return this->handle_close (); +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::info (char **strp, + size_t length) const +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::info"); + char buf[BUFSIZ]; + char addr_str[BUFSIZ]; + PR_AD addr; + + if (this->peer_acceptor_.get_local_addr (addr) == -1) + return -1; + else if (addr.addr_to_string (addr_str, sizeof addr) == -1) + return -1; + + ACE_OS::sprintf (buf, "%s\t %s %s", "ACE_Oneshot_Acceptor", + addr_str, "#oneshot acceptor factory\n"); + + if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, buf, length); + return ACE_OS::strlen (buf); +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::suspend (void) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::suspend"); + return this->reactor_ && this->reactor_->suspend_handler (this); +} + +template <class SH, PR_AC_1> int +ACE_Oneshot_Acceptor<SH, PR_AC_2>::resume (void) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::resume"); + return this->reactor_ && this->reactor_->resume_handler (this); +} + +// Returns ACE_HANDLE of the underlying peer_acceptor. + +template <class SH, PR_AC_1> ACE_HANDLE +ACE_Oneshot_Acceptor<SH, PR_AC_2>::get_handle (void) const +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::get_handle"); + return this->peer_acceptor_.get_handle (); +} + +template <class SH, PR_AC_1> ACE_PEER_ACCEPTOR & +ACE_Oneshot_Acceptor<SH, PR_AC_2>::acceptor (void) const +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::acceptor"); + return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; +} + +template <class SH, PR_AC_1> +ACE_Oneshot_Acceptor<SH, PR_AC_2>::operator ACE_PEER_ACCEPTOR & () const +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::operator ACE_PEER_ACCEPTOR &"); + return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; +} + +template <class SH, PR_AC_1> ACE_Reactor * +ACE_Oneshot_Acceptor<SH, PR_AC_2>::reactor (void) const +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::reactor"); + return this->reactor_; +} + +template <class SH, PR_AC_1> void +ACE_Oneshot_Acceptor<SH, PR_AC_2>::reactor (ACE_Reactor *r) +{ + ACE_TRACE ("ACE_Oneshot_Acceptor<SH, PR_AC_2>::reactor"); + this->reactor_ = r; +} + +#undef SH +#undef PR_AC_1 +#undef PR_AC_2 +#undef PR_AD +#endif /* ACE_ACCEPTOR_C */ diff --git a/ace/Acceptor.h b/ace/Acceptor.h new file mode 100644 index 00000000000..9b9ab8410bf --- /dev/null +++ b/ace/Acceptor.h @@ -0,0 +1,479 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Acceptor.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_ACCEPTOR_H) +#define ACE_ACCEPTOR_H + +#include "ace/Service_Config.h" +#include "ace/Service_Object.h" +#include "ace/Svc_Handler.h" +#include "ace/Strategies.h" + +template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> +class ACE_Acceptor : public ACE_Service_Object + // = TITLE + // Abstract factory for creating a service handler + // (SVC_HANDLER), accepting into the SVC_HANDLER, and + // activating the SVC_HANDLER. + // + // = DESCRIPTION + // Implements the basic strategy for passively establishing + // connections with clients. An ACE_Acceptor is parameterized + // by concrete types that conform to the interfaces of + // PEER_ACCEPTOR and SVC_HANDLER. The PEER_ACCEPTOR is + // instantiated with a transport mechanism that passively + // establishes connections. The SVC_HANDLER is instantiated + // with a concrete type that performs the application-specific + // service. An ACE_Acceptor inherits from ACE_Service_Object, + // which in turn inherits from ACE_Event_Handler. This enables + // the ACE_Reactor to dispatch the ACE_Acceptor's handle_input + // method when connection events occur. The handle_input method + // performs the ACE_Acceptor's default creation, connection + // establishment, and service activation strategies. These + // strategies can be overridden by subclasses individually or as + // a group. +{ +public: + // = Initialization and termination methods. + ACE_Acceptor (ACE_Reactor * = 0); + // "Do-nothing" constructor. + + ACE_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr, + ACE_Reactor * = ACE_Service_Config::reactor ()); + // Initialize and register <this> with the Reactor and listen for + // connection requests at the designated <local_addr>. + + int open (const ACE_PEER_ACCEPTOR_ADDR &, + ACE_Reactor * = ACE_Service_Config::reactor ()); + // Initialize and register <this> with the Reactor and listen for + // connection requests at the designated <local_addr>. + + virtual ~ACE_Acceptor (void); + // Close down the Acceptor's resources. + + virtual operator ACE_PEER_ACCEPTOR &() const; + // Return the underlying PEER_ACCEPTOR object. + + virtual ACE_PEER_ACCEPTOR &acceptor (void) const; + // Return the underlying PEER_ACCEPTOR object. + + ACE_Reactor *reactor (void) const; + // Get the underlying Reactor *. + + void reactor (ACE_Reactor *); + // Set the underlying Reactor *. + + virtual ACE_HANDLE get_handle (void) const; + // Returns the listening acceptor's <ACE_HANDLE>. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = The following three methods define the Acceptor's strategies + // for creating, accepting, and activating SVC_HANDLER's, + // respectively. + + virtual SVC_HANDLER *make_svc_handler (void); + // Bridge method for creating a SVC_HANDLER. The default is to + // create a new SVC_HANDLER. However, subclasses can override this + // policy to perform SVC_HANDLER creation in any way that they like + // (such as creating subclass instances of SVC_HANDLER, using a + // singleton, dynamically linking the handler, etc.). + + virtual int accept_svc_handler (SVC_HANDLER *svc_handler); + // Bridge method for accepting the new connection into the + // <svc_handler>. The default behavior delegates to the + // PEER_ACCEPTOR::accept. + + virtual int activate_svc_handler (SVC_HANDLER *svc_handler); + // Bridge method for activating a <svc_handler> with the appropriate + // concurrency strategy. The default behavior of this method is to + // activate the SVC_HANDLER by calling its open() method (which + // allows the SVC_HANDLER to define its own concurrency strategy). + // However, subclasses can override this strategy to do more + // sophisticated concurrency activations (such as making the + // SVC_HANDLER as an "active object" via multi-threading or + // multi-processing). + + // = Demultiplexing hooks. + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::RWE_MASK); + // Perform termination activities when <this> is removed from the + // <reactor_>. + + virtual int handle_input (ACE_HANDLE); + // Accepts all pending connections from clients, and creates and + // activates SVC_HANDLERs. + + // = Dynamic linking hooks. + virtual int init (int argc, char *argv[]); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int fini (void); + // Calls <handle_close>. + + virtual int info (char **buf, size_t) const; + // Default version returns address info in <buf>. + + // = Service management hooks. + virtual int suspend (void); + // This method calls <Reactor::suspend>. + + virtual int resume (void); + // This method calls <Reactor::resume>. + +private: + ACE_Reactor *reactor_; + // Event demultiplexer associated with this object. + + ACE_PEER_ACCEPTOR peer_acceptor_; + // Concrete factory for accepting connections from clients... +}; + +template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> +class ACE_Strategy_Acceptor : public ACE_Acceptor <SVC_HANDLER, ACE_PEER_ACCEPTOR_2> + // = TITLE + // Abstract factory for creating a service handler + // (SVC_HANDLER), accepting into the SVC_HANDLER, and activating + // the SVC_HANDLER. + // + // = DESCRIPTION + // Implements a flexible and extensible set of strategies for + // passively establishing connections with clients. There are + // three main strategies: (1) creating a SVC_HANDLER, (2) + // passively accepting a new connection from a client into the + // SVC_HANDLER, and (3) activating the SVC_HANDLER with a + // particular concurrency mechanism. +{ +public: + // = Initialization and termination methods. + ACE_Strategy_Acceptor (const char service_name[] = 0, + const char service_description[] = 0); + // Default constructor. + + ACE_Strategy_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr, + ACE_Reactor * = ACE_Service_Config::reactor (), + ACE_Creation_Strategy<SVC_HANDLER> * = 0, + ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> * = 0, + ACE_Concurrency_Strategy<SVC_HANDLER> * = 0, + ACE_Scheduling_Strategy<SVC_HANDLER> * = 0, + const char service_name[] = 0, + const char service_description[] = 0); + // Initialize the appropriate strategies for creation, passive + // connection acceptance, and concurrency, and then register <this> + // with the Reactor and listen for connection requests at the + // designated <local_addr>. + + int open (const ACE_PEER_ACCEPTOR_ADDR &, + ACE_Reactor * = ACE_Service_Config::reactor (), + ACE_Creation_Strategy<SVC_HANDLER> * = 0, + ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> * = 0, + ACE_Concurrency_Strategy<SVC_HANDLER> * = 0, + ACE_Scheduling_Strategy<SVC_HANDLER> * = 0, + const char service_name[] = 0, + const char service_description[] = 0); + // Initialize the appropriate strategies for creation, passive + // connection acceptance, and concurrency, and then register <this> + // with the Reactor and listen for connection requests at the + // designated <local_addr>. + + virtual ~ACE_Strategy_Acceptor (void); + // Close down the Strategy_Acceptor's resources. + + virtual operator ACE_PEER_ACCEPTOR &() const; + // Return the underlying PEER_ACCEPTOR object. + + virtual ACE_PEER_ACCEPTOR &acceptor (void) const; + // Return the underlying PEER_ACCEPTOR object. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Service management hooks. + + virtual int suspend (void); + // This method delegates to the <Scheduling_Strategy>'s <suspend> + // method. + + virtual int resume (void); + // This method delegates to the <Scheduling_Strategy>'s <resume> + // method. + + virtual int fini (void); + // Calls <handle_close> when dynamically unlinked. + + virtual int info (char **buf, size_t) const; + // Default version returns address info in <buf>. + + // = The following three methods define the <Acceptor>'s strategies + // for creating, accepting, and activating <SVC_HANDLER>'s, + // respectively. + + virtual SVC_HANDLER *make_svc_handler (void); + // Bridge method for creating a <SVC_HANDLER>. The strategy for + // creating a <SVC_HANDLER> are configured into the Acceptor via + // it's <creation_strategy_>. The default is to create a new + // <SVC_HANDLER>. However, subclasses can override this policy to + // perform <SVC_HANDLER> creation in any way that they like (such as + // creating subclass instances of <SVC_HANDLER>, using a singleton, + // dynamically linking the handler, etc.). + + virtual int accept_svc_handler (SVC_HANDLER *svc_handler); + // Bridge method for accepting the new connection into the + // <SVC_HANDLER>. The default behavior delegates to the + // <PEER_ACCEPTOR::accept> in the <Acceptor_Strategy>. + + virtual int activate_svc_handler (SVC_HANDLER *svc_handler); + // Bridge method for activating a <SVC_HANDLER> with the appropriate + // concurrency strategy. The default behavior of this method is to + // activate the <SVC_HANDLER> by calling its <open> method (which + // allows the <SVC_HANDLER> to define its own concurrency strategy). + // However, subclasses can override this strategy to do more + // sophisticated concurrency activations (such as creating the + // <SVC_HANDLER> as an "active object" via multi-threading or + // multi-processing). + + // = Demultiplexing hooks. + virtual ACE_HANDLE get_handle (void) const; + // Returns the listening acceptor's <ACE_HANDLE>. + + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::RWE_MASK); + // Perform termination activities when <this> is removed from the + // <Reactor>. + + virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); + // Handle SIGINT. + + // = These data members are "logically private" but are put in the + // protected part in case subclasses want to access them. + + // = Define some useful typedefs. + typedef ACE_Creation_Strategy<SVC_HANDLER> CREATION_STRATEGY; + typedef ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> ACCEPT_STRATEGY; + typedef ACE_Concurrency_Strategy<SVC_HANDLER> CONCURRENCY_STRATEGY; + typedef ACE_Scheduling_Strategy<SVC_HANDLER> SCHEDULING_STRATEGY; + + // = Strategy objects. + + CREATION_STRATEGY *creation_strategy_; + // Creation strategy for an Acceptor. + + int delete_creation_strategy_; + // 1 if <Acceptor> created the creation strategy and thus should + // delete it, else 0. + + ACCEPT_STRATEGY *accept_strategy_; + // Accept strategy for an <Acceptor>. + + int delete_accept_strategy_; + // 1 if <Acceptor> created the accept strategy and thus should delete + // it, else 0. + + CONCURRENCY_STRATEGY *concurrency_strategy_; + // Concurrency strategy for an <Acceptor>. + + int delete_concurrency_strategy_; + // 1 if <Acceptor> created the concurrency strategy and thus should + // delete it, else 0. + + SCHEDULING_STRATEGY *scheduling_strategy_; + // Scheduling strategy for an <Acceptor>. + + int delete_scheduling_strategy_; + // 1 if <Acceptor> created the scheduling strategy and thus should + // delete it, else 0. + + // = Service information objects. + + char *service_name_; + // Name of the service. + + char *service_description_; + // Description of the service. + + u_short service_port_; + // Port number for the server. + + ACE_PEER_ACCEPTOR_ADDR service_addr_; + // Address that the <Strategy_Acceptor> uses to listen for + // connections. +}; + +template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> +class ACE_Oneshot_Acceptor : public ACE_Service_Object + // = TITLE + // Generic factory for passively connecting clients and creating + // exactly one service handler (SVC_HANDLER). + // + // = DESCRIPTION + // This class works similarly to the regular acceptor except + // that this class doesn't need a Creation_Strategy (since the + // user supplies the SVC_HANDLER) or an Accept_Strategy (since + // this class only accepts one connection and then removes all + // traces (e.g., from the ACE_Reactor). +{ +public: + // = Initialization and termination methods. + ACE_Oneshot_Acceptor (void); + // "Do-nothing" constructor. + + ACE_Oneshot_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &, + ACE_Reactor * = ACE_Service_Config::reactor (), + ACE_Concurrency_Strategy<SVC_HANDLER> * = 0); + // Initialize the appropriate strategies for concurrency and + // creation and then register <this> at the designated <local_addr>. + + int open (const ACE_PEER_ACCEPTOR_ADDR &, + ACE_Reactor * = ACE_Service_Config::reactor (), + ACE_Concurrency_Strategy<SVC_HANDLER> * = 0); + // Initialize the appropriate strategies for concurrency and + // creation and then register <this> at the designated <local_addr>. + + virtual ~ACE_Oneshot_Acceptor (void); + // Close down the <Oneshot_Acceptor>. + + // = Explicit factory operation. + virtual int accept (SVC_HANDLER * = 0, + ACE_PEER_ACCEPTOR_ADDR *remote_addr = 0, + const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, + int restart = 1); + // Create a SVC_HANDLER, accept the connection into the SVC_HANDLER, + // and activate the SVC_HANDLER. + + virtual int cancel (void); + // Cancel a oneshot acceptor that was started asynchronously. + + virtual operator ACE_PEER_ACCEPTOR &() const; + // Return the underlying PEER_ACCEPTOR object. + + virtual ACE_PEER_ACCEPTOR &acceptor (void) const; + // Return the underlying PEER_ACCEPTOR object. + + ACE_Reactor *reactor (void) const; + // Get the underlying Reactor *. + + void reactor (ACE_Reactor *); + // Set the underlying Reactor *. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + virtual int activate_svc_handler (SVC_HANDLER *svc_handler); + // Bridge method for activating a <svc_handler> with the appropriate + // concurrency strategy. Default behavior is to activate the + // SVC_HANDLER as a "passive object." However, subclasses can + // override this strategy to do more sophisticated concurrency + // activations (such as creating the SVC_HANDLER as an "active + // object" via multi-threading or multi-processing). + + int shared_accept (SVC_HANDLER *svc_handler, + ACE_PEER_ACCEPTOR_ADDR *remote_addr, + ACE_Time_Value *timeout, + int restart); + // Factors out the code shared between the <accept> and + // <handle_input> methods. + + int register_handler (SVC_HANDLER *svc_handler, + const ACE_Synch_Options &options, + int restart); + // Insert ourselves into the ACE_Reactor so that we can + // continue accepting this connection asynchronously. + + // = Demultiplexing hooks. + virtual ACE_HANDLE get_handle (void) const; + // Returns the listening acceptor's <ACE_HANDLE>. + + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::RWE_MASK); + // Perform termination activities when <this> is removed from the + // <reactor_>. + + virtual int handle_input (ACE_HANDLE); + // Accept one connection from a client and activates the + // SVC_HANDLER. + + virtual int handle_timeout (const ACE_Time_Value &tv, + const void *arg); + // Called when an acceptor times out... + + // = Dynamic linking hooks. + virtual int init (int argc, char *argv[]); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int fini (void); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int info (char **, size_t) const; + // Default version returns address info in <buf>. + + // = Service management hooks. + virtual int suspend (void); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int resume (void); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + +private: + ACE_Reactor *reactor_; + // Event demultiplexer associated with this object. + + SVC_HANDLER *svc_handler_; + // Hold the svc_handler_ across asynchrony boundaries. + + int restart_; + // Hold the restart flag across asynchrony boundaries. + + ACE_PEER_ACCEPTOR peer_acceptor_; + // Factory that establishes connections passively. + + ACE_Concurrency_Strategy<SVC_HANDLER> *concurrency_strategy_; + // Concurrency strategy for an Acceptor. + + int delete_concurrency_strategy_; + // 1 if Acceptor created the concurrency strategy and thus should + // delete it, else 0. +}; + +#include "ace/Acceptor.i" + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Acceptor.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Acceptor.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_ACCEPTOR_H */ diff --git a/ace/Acceptor.i b/ace/Acceptor.i new file mode 100644 index 00000000000..3cf904fc7e2 --- /dev/null +++ b/ace/Acceptor.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Acceptor.i diff --git a/ace/Activation_Queue.cpp b/ace/Activation_Queue.cpp new file mode 100644 index 00000000000..e536bfb030f --- /dev/null +++ b/ace/Activation_Queue.cpp @@ -0,0 +1,70 @@ +// Activation_Queue.cpp +// $Id$ + +#define ACE_BUILD_DLL + +#include "ace/Activation_Queue.h" + +// Dump the state of an object. + +void +ACE_Activation_Queue::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, + "delete_queue_ = %d\n", + this->delete_queue_)); + ACE_DEBUG ((LM_INFO,"queue_: \n")); + if (this->queue_) + this->queue_->dump(); + else + ACE_DEBUG ((LM_DEBUG,"(NULL)\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Activation_Queue::ACE_Activation_Queue (ACE_Message_Queue<ACE_SYNCH> *new_queue) + : delete_queue_ (0) +{ + if (new_queue) + this->queue_ = new_queue; + else + { + ACE_NEW (this->queue_, ACE_Message_Queue<ACE_SYNCH>); + this->delete_queue_ = 1; + } +} + +ACE_Activation_Queue::~ACE_Activation_Queue (void) +{ + if (this->delete_queue_ != 0) + delete this->queue_; +} + +ACE_Method_Object * +ACE_Activation_Queue::dequeue (ACE_Time_Value *tv) +{ + ACE_Message_Block *mb; + ACE_Method_Object *mo; + + // Dequeue the message. + this->queue_->dequeue_head (mb, tv); + + // Get the method object. + mo = (ACE_Method_Object *) mb->base (); + + // Delete the message block. + delete mb; + return mo; +} + +int +ACE_Activation_Queue::enqueue (ACE_Method_Object *mo, + ACE_Time_Value *tv) +{ + ACE_Message_Block *mb; + + ACE_NEW_RETURN (mb, ACE_Message_Block ((char *) mo), -1); + + return this->queue_->enqueue (mb, tv); +} + diff --git a/ace/Activation_Queue.h b/ace/Activation_Queue.h new file mode 100644 index 00000000000..2ab871dce7e --- /dev/null +++ b/ace/Activation_Queue.h @@ -0,0 +1,63 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Activation_Queue.h +// +// = AUTHOR +// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt +// <schmidt@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_ACTIVATION_QUEUE_H) +#define ACE_ACTIVATION_QUEUE_H + +#include "ace/Synch.h" +#include "ace/Message_Queue.h" +#include "ace/Method_Object.h" + +class ACE_Export ACE_Activation_Queue + // = TITLE + // Reifies a method into an object. Subclasses typically + // represent necessary state and behavior. + // + // = DESCRIPTION + // A <Method_Object> is inserted in the <Activation_Queue>, where + // it is subsequently removed by the <Scheduler> and invoked. +{ +public: + // = Initialization and termination methods. + ACE_Activation_Queue (ACE_Message_Queue<ACE_SYNCH> *new_queue = 0); + ~ACE_Activation_Queue (void); + + // = Queue operations. + ACE_Method_Object *dequeue (ACE_Time_Value *tv = 0); + // Dequeue the next available <Method_Object>. + + int enqueue (ACE_Method_Object *new_method_object, + ACE_Time_Value *tv = 0); + // Enqueue the <Method_Object>. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Message_Queue<ACE_SYNCH> *queue_; + // Stores the <Method_Objects>. + + int delete_queue_; + // Keeps track of whether we need to delete the queue. +}; + +#endif /* ACE_ACTIVATION_QUEUE_H */ + diff --git a/ace/Addr.cpp b/ace/Addr.cpp new file mode 100644 index 00000000000..39edb5fe6d2 --- /dev/null +++ b/ace/Addr.cpp @@ -0,0 +1,44 @@ +// Addr.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Addr.h" + +// This is a static class variable. +const ACE_Addr ACE_Addr::sap_any; + +#if !defined (__ACE_INLINE__) +#include "ace/Addr.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Addr) + +void +ACE_Addr::dump (void) const +{ + ACE_TRACE ("ACE_Addr::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "addr_type_ = %d", this->addr_type_)); + ACE_DEBUG ((LM_DEBUG, "\naddr_size_ = %d", this->addr_size_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Initializes instance variables. + +void +ACE_Addr::base_set (int type, int size) +{ + this->addr_type_ = type; + this->addr_size_ = size; +} + +// Initializes instance variables. Note that 0 is an unspecified +// protocol family type... + +ACE_Addr::ACE_Addr (int type, int size) +{ + this->base_set (type, size); +} + diff --git a/ace/Addr.h b/ace/Addr.h new file mode 100644 index 00000000000..3108674edc3 --- /dev/null +++ b/ace/Addr.h @@ -0,0 +1,93 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Addr.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_ADDR_H) +#define ACE_ADDR_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Addr + // = TITLE + // Defines the base class for the "address family independent" + // address format. +{ +public: + // = Initialization method. + + ACE_Addr (int type = 0, int size = 0); + // Initializes instance variables. + + // = Get/set the size of the address. + + int get_size (void) const; + // Return the size of the address. + + void set_size (int size); + // Sets the size of the address. + + // = Get/set the type of the address. + + int get_type (void) const; + // Get the type of the address. + + void set_type (int type); + // Set the type of the address. + + virtual void *get_addr (void) const; + // Return a pointer to the address. + + virtual void set_addr (void *, int len); + // Set a pointer to the address. + + virtual int addr_to_string (char addr[], size_t) const; + // Transform the current address into string format. + + virtual int string_to_addr (const char addr[]); + // Transform the string into the current addressing format. + + // = Equality/inequality tests + virtual int operator == (const ACE_Addr &sap) const; + // Check for address equality. + + virtual int operator != (const ACE_Addr &sap) const; + // Check for address inequality. + + void base_set (int type, int size); + // Initializes instance variables. + + static const ACE_Addr sap_any; + // Wild-card address. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + int addr_type_; + // e.g., AF_UNIX, AF_INET, AF_SPIPE, etc. + + int addr_size_; + // Number of bytes in the address. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Addr.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_ADDR_H */ diff --git a/ace/Addr.i b/ace/Addr.i new file mode 100644 index 00000000000..30ce46a1f62 --- /dev/null +++ b/ace/Addr.i @@ -0,0 +1,77 @@ +/* -*- C++ -*- */ +// $Id$ + +// Addr.i + +// Return the address of the address. + +ACE_INLINE void * +ACE_Addr::get_addr (void) const +{ + return 0; +} + +ACE_INLINE void +ACE_Addr::set_addr (void *, int) +{ +} + +// Transform the current address into string format. + +ACE_INLINE int +ACE_Addr::addr_to_string (char [], size_t) const +{ + return -1; +} + +// Transform the string into the current addressing format. + +ACE_INLINE int +ACE_Addr::string_to_addr (const char []) +{ + return -1; +} + +ACE_INLINE int +ACE_Addr::operator == (const ACE_Addr &sap) const +{ + return sap.addr_type_ == 0; +} + +ACE_INLINE int +ACE_Addr::operator != (const ACE_Addr &sap) const +{ + return sap.addr_type_ != 0; +} + +// Return the size of the address. + +ACE_INLINE int +ACE_Addr::get_size (void) const +{ + return this->addr_size_; +} + +// Sets the size of the address. + +ACE_INLINE void +ACE_Addr::set_size (int size) +{ + this->addr_size_ = size; +} + +// Return the type of the address. + +ACE_INLINE int +ACE_Addr::get_type (void) const +{ + return this->addr_type_; +} + +// Set the type of the address. + +ACE_INLINE void +ACE_Addr::set_type (int type) +{ + this->addr_type_ = type; +} diff --git a/ace/Auto_Ptr.cpp b/ace/Auto_Ptr.cpp new file mode 100644 index 00000000000..67bc370b505 --- /dev/null +++ b/ace/Auto_Ptr.cpp @@ -0,0 +1,50 @@ +// Auto_Ptr.cpp +// $Id$ + +#if !defined (ACE_AUTO_PTR_C) +#define ACE_AUTO_PTR_C + +#define ACE_BUILD_DLL +#include "ace/Auto_Ptr.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Auto_Ptr.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(auto_ptr) + +template<class X> void +auto_ptr<X>::dump (void) const +{ + ACE_TRACE ("auto_ptr<X>::dump"); +} + +template<class X> void +auto_ptr<X>::remove (X *& x) +{ + ACE_TRACE ("auto_ptr<X>::remove"); + + X *tp = x; + x = 0; + delete tp; +} + +ACE_ALLOC_HOOK_DEFINE(auto_array_ptr) + +template<class X> void +auto_array_ptr<X>::dump (void) const +{ + ACE_TRACE ("auto_array_ptr<X>::dump"); +} + +template<class X> void +auto_array_ptr<X>::remove (X *& x) +{ + ACE_TRACE ("auto_array_ptr<X>::remove"); + + X *tp = x; + x = 0; + delete [] tp; +} + +#endif /* ACE_AUTO_PTR_C */ diff --git a/ace/Auto_Ptr.h b/ace/Auto_Ptr.h new file mode 100644 index 00000000000..57251fec225 --- /dev/null +++ b/ace/Auto_Ptr.h @@ -0,0 +1,101 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Auto_Ptr.h +// +// = AUTHOR +// Doug Schmidt, based on code from Jack Reeves (jack@fx.com) and +// Dr. Harald M. Mueller (mueller@garwein.hai.siemens.co.at) +// +// ============================================================================ + +#if !defined (ACE_AUTO_PTR_H) +#define ACE_AUTO_PTR_H + +#include "ace/ACE.h" + +template <class X> +class auto_ptr + // = TITLE + // Implements the draft C++ standard auto_ptr abstraction. +{ +public: + // = Initialization and termination methods + auto_ptr (X *p = 0); + auto_ptr (auto_ptr<X> &ap); + ~auto_ptr (void); + void operator= (auto_ptr<X> &rhs); + + // = Accessor methods. + X &operator *() const; + X *operator-> () const; + X *get (void) const; + X *release (void); + X *reset (X *p); + + static void remove (X* &x); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + X *p_; +}; + +template<class X> +class auto_array_ptr + // = TITLE + // Implements an extension to the draft C++ standard auto_ptr + // abstraction. +{ +public: + // = Initialization and termination methods. + auto_array_ptr (X *p = 0); + auto_array_ptr (auto_array_ptr<X> &ap); + ~auto_array_ptr (void); + void operator= (auto_array_ptr<X> &rhs); + + // = Accessor methods. + X &operator* (); + X *operator-> (); + X &operator[] (int i); + X operator[] (int i) const; + X *get (void) const; + X *release (void); + X *reset (X *p); + + static void remove (X *&x); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + X *p_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Auto_Ptr.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Auto_Ptr.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Auto_Ptr.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_AUTO_PTR_H */ diff --git a/ace/Auto_Ptr.i b/ace/Auto_Ptr.i new file mode 100644 index 00000000000..f0209505c17 --- /dev/null +++ b/ace/Auto_Ptr.i @@ -0,0 +1,151 @@ +/* -*- C++ -*- */ +// $Id$ + +// Auto_Ptr.i + +template<class X> ACE_INLINE void +auto_ptr<X>::operator= (auto_ptr<X> &rhs) +{ + ACE_TRACE ("auto_ptr<X>::operator="); + if (this != &rhs) + { + auto_ptr<X>::remove (p_); + p_ = rhs.release (); + } +} + +template<class X> ACE_INLINE +auto_ptr<X>::auto_ptr (X *p) + : p_ (p) +{ + ACE_TRACE ("auto_ptr<X>::auto_ptr"); +} + +template<class X> ACE_INLINE +auto_ptr<X>::auto_ptr (auto_ptr<X> &ap) + : p_ (ap.release ()) +{ + ACE_TRACE ("auto_ptr<X>::auto_ptr"); +} + +template<class X> ACE_INLINE +auto_ptr<X>::~auto_ptr (void) +{ + ACE_TRACE ("auto_ptr<X>::~auto_ptr"); + delete p_; +} + +template<class X> ACE_INLINE X & +auto_ptr<X>::operator *() const +{ + return *p_; +} + +template<class X> ACE_INLINE X * +auto_ptr<X>::operator-> () const +{ + ACE_TRACE ("auto_ptr<X>::operator->"); + return p_; +} + +template<class X> ACE_INLINE X * +auto_ptr<X>::get (void) const +{ + ACE_TRACE ("auto_ptr<X>::get"); + return p_; +} + +template<class X> ACE_INLINE X * +auto_ptr<X>::release (void) +{ + ACE_TRACE ("auto_ptr<X>::release"); + return this->reset (0); +} + +template<class X> ACE_INLINE X * +auto_ptr<X>::reset (X *p) +{ + ACE_TRACE ("auto_ptr<X>::reset"); + X *tp = p_; + p_ = p; + return tp; +} + +template<class X> ACE_INLINE +auto_array_ptr<X>::auto_array_ptr (X *p) + : p_ (p) +{ + ACE_TRACE ("auto_array_ptr<X>::auto_array_ptr"); +} + +template<class X> ACE_INLINE +auto_array_ptr<X>::auto_array_ptr (auto_array_ptr<X> &ap) + : p_ (ap.release ()) +{ + ACE_TRACE ("auto_array_ptr<X>::auto_array_ptr"); +} + +template<class X> ACE_INLINE +auto_array_ptr<X>::~auto_array_ptr (void) +{ + ACE_TRACE ("auto_array_ptr<X>::~auto_array_ptr"); + delete [] p_; +} + +template<class X> ACE_INLINE X & +auto_array_ptr<X>::operator*() +{ + return *p_; +} + +template<class X> ACE_INLINE X * +auto_array_ptr<X>::operator->() +{ + return p_; +} + +template<class X> ACE_INLINE X & +auto_array_ptr<X>::operator[](int i) +{ + return p_[i]; +} + +template<class X> ACE_INLINE X +auto_array_ptr<X>::operator[](int i) const +{ + return p_[i]; +} + +template<class X> ACE_INLINE X * +auto_array_ptr<X>::get (void) const +{ + ACE_TRACE ("auto_array_ptr<X>::get"); + return p_; +} + +template<class X> ACE_INLINE X * +auto_array_ptr<X>::release (void) +{ + ACE_TRACE ("auto_array_ptr<X>::release"); + return this->reset (0); +} + +template<class X> ACE_INLINE X * +auto_array_ptr<X>::reset (X *p) +{ + ACE_TRACE ("auto_array_ptr<X>::reset"); + X *tp = p_; + p_ = p; + return tp; +} + +template<class X> ACE_INLINE void +auto_array_ptr<X>::operator= (auto_array_ptr<X> &rhs) +{ + ACE_TRACE ("auto_array_ptr<X>::operator="); + if (this != &rhs) + { + auto_array_ptr<X>::remove (p_); + p_ = rhs.release (); + } +} diff --git a/ace/CORBA_Handler.cpp b/ace/CORBA_Handler.cpp new file mode 100644 index 00000000000..bd0fde609c4 --- /dev/null +++ b/ace/CORBA_Handler.cpp @@ -0,0 +1,522 @@ +// CORBA_Handler.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/CORBA_Handler.h" + +#if !defined (__ACE_INLINE__) +#include "ace/CORBA_Handler.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_HAS_ORBIX) +ACE_ALLOC_HOOK_DEFINE(ACE_ST_CORBA_Handler) +ACE_ALLOC_HOOK_DEFINE(ACE_CORBA_Handler) + +void +ACE_CORBA_Handler::dump (void) const +{ + ACE_TRACE ("ACE_CORBA_Handler::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "reactor_ = %x", this->reactor_)); + ACE_DEBUG ((LM_DEBUG, "\nreference_count_ = %d", this->reference_count_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_CORBA_Handler::ACE_CORBA_Handler (const ACE_CORBA_Handler &rhs) +{ + ACE_TRACE ("ACE_CORBA_Handler::ACE_CORBA_Handler"); +} + +const ACE_CORBA_Handler & +ACE_CORBA_Handler::operator= (const ACE_CORBA_Handler &rhs) +{ + ACE_TRACE ("ACE_CORBA_Handler::operator="); + return *this; +} + +void +ACE_ST_CORBA_Handler::dump (void) const +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::dump"); + + ACE_CORBA_Handler::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "instance_ = %x", this->instance_)); + ACE_DEBUG ((LM_DEBUG, "\niteration_ = %d", this->iterations_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_CORBA_Handler::~ACE_CORBA_Handler (void) +{ + ACE_TRACE ("ACE_CORBA_Handler::~ACE_CORBA_Handler"); +} + +ACE_CORBA_Handler::ACE_CORBA_Handler (void) + : reactor_ (ACE_Service_Config::reactor ()) +{ + ACE_TRACE ("ACE_CORBA_Handler::ACE_CORBA_Handler"); +} + +// Only one ST CORBA Handler per-process... +/* static */ +ACE_ST_CORBA_Handler *ACE_ST_CORBA_Handler::instance_ = 0; + +// Insert a descriptor into the ACE_Reactor that Orbix has just added. + +/* static */ +void +ACE_ST_CORBA_Handler::insert_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::insert_handle"); +// ACE_DEBUG ((LM_DEBUG, "+++ inserting %d\n", handle)); + + if (ACE_ST_CORBA_Handler::instance_->reactor_ != 0) + ACE_ST_CORBA_Handler::instance_->reactor_->register_handler + (handle, ACE_ST_CORBA_Handler::instance_, ACE_Event_Handler::READ_MASK); + else + ; +// ACE_DEBUG ((LM_DEBUG, "insert_handle: reactor NULL\n")); +} + +// Remove a descriptor from the ACE_Reactor that Orbix has just deleted. + +/* static */ +void +ACE_ST_CORBA_Handler::remove_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::remove_handle"); +// ACE_DEBUG ((LM_DEBUG, "--- removing %d\n", handle)); + + if (ACE_ST_CORBA_Handler::instance_->reactor_ != 0) + ACE_ST_CORBA_Handler::instance_->reactor_->remove_handler + (handle, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + else + ; +// ACE_DEBUG ((LM_DEBUG, "remove_handle: reactor NULL\n")); +} + +// Process the next Orbix event. + +int +ACE_ST_CORBA_Handler::handle_input (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::handle_input"); + // ACE_DEBUG ((LM_DEBUG, "dispatching Orbix handle = %d in process + // = %P\n", handle)); + + TRY { + // Loop up to <ACE_ST_CORBA_Handler::iterations_> dispatching the + // next event. Note the trade off between efficiency and + // fairness... + + for (size_t i = 0; i < this->iterations_; i++) + if (ACE_CORBA_1 (Orbix.isEventPending) (IT_X)) + // Process the next Orbix event (don't block). + ACE_CORBA_1 (Orbix.processNextEvent) (0, IT_X); + else + break; + } + CATCHANY { + // an error occured calling processNextEvent () - output the + // error. + cerr << IT_X << endl; + } ENDTRY; + return 0; +} + +int +ACE_ST_CORBA_Handler::suspend (void) +{ + // Create an iterator. + ACE_Handle_Set set (ACE_CORBA_1 (Orbix.getFileDescriptors) ()); + ACE_Handle_Set_Iterator orbix_descriptors (set); + + // Suspend all the HANDLEs registered by Orbix. + for (ACE_HANDLE h; + (h = orbix_descriptors ()) != ACE_INVALID_HANDLE; + ++orbix_descriptors) + this->reactor_->suspend_handler (h); + + return 0; +} + +int +ACE_ST_CORBA_Handler::resume (void) +{ + // Create an iterator. + ACE_Handle_Set set (ACE_CORBA_1 (Orbix.getFileDescriptors) ()); + ACE_Handle_Set_Iterator orbix_descriptors (set); + + // Resume all the HANDLEs registered by Orbix. + for (ACE_HANDLE h; + (h = orbix_descriptors ()) != ACE_INVALID_HANDLE; + ++orbix_descriptors) + this->reactor_->resume_handler (h); + + return 0; +} + +// Dummy constructor. +ACE_ST_CORBA_Handler::ACE_ST_CORBA_Handler (void) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::ACE_ST_CORBA_Handler"); + + // This is set by default for backward compatibility. The user can + // use the set/get operations to change the iterations + this->iterations_ = 5; + + // Set up the callbacks so that we get informed when Orbix changes + // its descriptors. + ACE_CORBA_1 (Orbix.registerIOCallback) ((OrbixIOCallback) &ACE_ST_CORBA_Handler::insert_handle, + FD_OPEN_CALLBACK); + ACE_CORBA_1 (Orbix.registerIOCallback) ((OrbixIOCallback) &ACE_ST_CORBA_Handler::remove_handle, + FD_CLOSE_CALLBACK); +} + +void +ACE_ST_CORBA_Handler::get_orbix_descriptors (void) +{ + // Create an iterator. + ACE_Handle_Set set (ACE_CORBA_1 (Orbix.getFileDescriptors) ()); + ACE_Handle_Set_Iterator orbix_descriptors (set); + + // Preinitialize anything that's already registered. + for (ACE_HANDLE h; + (h = orbix_descriptors ()) != ACE_INVALID_HANDLE; + ++orbix_descriptors) + ACE_ST_CORBA_Handler::insert_handle (h); +} + +// Register <service_name> by doing a "putit" to register the +// <service_name> using the <marker_name> at <service_location> with +// orbixd. + +/* static */ +int +ACE_CORBA_Handler::register_service (const char *service_name, + const char *marker_name, + const char *service_location) +{ + ACE_TRACE ("ACE_CORBA_Handler::register_service"); + char buf[BUFSIZ * 2]; // I hope this is enough space... + + // Be defensive here... + if (service_name == 0 || service_location == 0) + { + errno = EINVAL; + return -1; + } + else if (marker_name == 0) + ACE_OS::sprintf (buf, "putit %s %s", service_name, service_location); + else + ACE_OS::sprintf (buf, "putit -marker %s %s %s", + marker_name, service_name, service_location); + + return ACE_OS::system (buf); // Use system(3S) to execute Orbix putit. +} + +// Register <service_name> by doing a "putit" to register +// <service_name> using the <marker_name> with orbixd. + +/* static */ +int +ACE_CORBA_Handler::remove_service (const char *service_name, + const char *marker_name) +{ + ACE_TRACE ("ACE_CORBA_Handler::remove_service"); + char buf[BUFSIZ * 2]; // I hope this is enough space! + if (service_name == 0) + { + errno = EINVAL; + return -1; + } + else if (marker_name == 0) + ACE_OS::sprintf (buf, "rmit %s\n", service_name); + else + ACE_OS::sprintf (buf, "rmit -marker %s %s\n", marker_name, service_name); + return ACE_OS::system (buf); // Use system(3S) to execute Orbix rmit. +} + +ACE_ST_CORBA_Handler::~ACE_ST_CORBA_Handler (void) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::~ACE_ST_CORBA_Handler"); + // Create an iterator. + ACE_Handle_Set set (ACE_CORBA_1 (Orbix.getFileDescriptors) ()); + ACE_Handle_Set_Iterator orbix_descriptors (set); + + // Remove everything! + + for (ACE_HANDLE h; + (h = orbix_descriptors ()) != ACE_INVALID_HANDLE; + ++orbix_descriptors) + ACE_ST_CORBA_Handler::remove_handle (h); + + // Keep Orbix from calling us back and crashing the system! + ACE_CORBA_1 (Orbix.registerIOCallback) (0, FD_OPEN_CALLBACK); + ACE_CORBA_1 (Orbix.registerIOCallback) (0, FD_CLOSE_CALLBACK); + ACE_ST_CORBA_Handler::instance_ = 0; +} + +// Decrement the reference count and free up all the resources if this +// is the last service to be using the ACE_ST_CORBA_Handler... + +/* static */ +int +ACE_CORBA_Handler::deactivate_service (const char *service_name, + const char *marker_name) +{ + ACE_TRACE ("ACE_CORBA_Handler::deactivate_service"); + if (service_name != 0 + && this->remove_service (service_name, marker_name) == -1) + return -1; + + int ref_count = this->reference_count_; + + this->reference_count_--; + + // Close everything down if the count drops to 0. + if (this->reference_count_ == 0) + // Commit suicide! + delete this; + + if (ref_count < 0) + ; +// ACE_DEBUG ((LM_DEBUG, "warning, reference count == %d\n", +// ref_count)); + return 0; +} + +/* static */ +ACE_CORBA_Handler * +ACE_ST_CORBA_Handler::instance (void) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::instance"); + + // Note that this does not need a double-check since it should be + // called from a single-threaded environment. + + if (ACE_ST_CORBA_Handler::instance_ == 0) + { + ACE_NEW_RETURN (ACE_ST_CORBA_Handler::instance_, ACE_ST_CORBA_Handler, 0); + ACE_ST_CORBA_Handler::instance_->get_orbix_descriptors (); + } + + return ACE_ST_CORBA_Handler::instance_; +} + +// Activate and register <service_name> with the Orbix daemon. If +// <marker_name> and <service_location> are != 0 then do a "putit" to +// register this service with orbixd. This method also increments the +// reference count of active services using the ACE_ST_CORBA_Handler. + +int +ACE_CORBA_Handler::activate_service (const char *service_name, + const char *marker_name, + const char *service_location) +{ + ACE_TRACE ("ACE_CORBA_Handler::activate_service"); + // Since the ACE_CORBA_Handler is a singleton, make sure not to + // allocate and initialize more than one copy. By incrementing the + // reference count we ensure this. + + this->reference_count_++; + + if (service_name != 0 && service_location != 0 + && this->register_service (service_name, marker_name, + service_location) == -1) + return -1; + + // Tell Orbix that we have completed the server's initialization. + // Note that we don't block by giving a timeout of 0... + + TRY { + ACE_CORBA_1 (Orbix.impl_is_ready) ((char *) service_name, 0, IT_X); + } CATCHANY { + return -1; + } ENDTRY + + return 0; +} + +#if defined (ACE_HAS_MT_ORBIX) + +ACE_ALLOC_HOOK_DEFINE(ACE_MT_CORBA_Handler) + +#if defined (ACE_MT_SAFE) +// Synchronize output operations. +ACE_Thread_Mutex ACE_MT_CORBA_Handler::ace_mt_corba_handler_lock_; +#endif /* ACE_MT_SAFE */ + +void +ACE_MT_CORBA_Handler::dump (void) const +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::dump"); + ACE_CORBA_Handler::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "instance_ = %x", this->instance_)); + ACE_DEBUG ((LM_DEBUG, "\nthr_mgr_ = %x", this->thr_mgr_)); + this->pipe_.dump (); +#if defined (ACE_MT_SAFE) + // Double-Check lock. + ace_mt_corba_handler_lock_.dump (); +#endif /* ACE_MT_SAFE */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Only one MT CORBA Handler per-process... +/* static */ +ACE_MT_CORBA_Handler *ACE_MT_CORBA_Handler::instance_ = 0; + +/* static */ +ACE_CORBA_Handler * +ACE_MT_CORBA_Handler::instance (void) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::instance"); + + if (ACE_MT_CORBA_Handler::instance_ == 0) + { + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_MT_CORBA_Handler::ace_mt_corba_handler_lock_, 0); + + if (ACE_MT_CORBA_Handler::instance_ == 0) + ACE_NEW_RETURN (ACE_MT_CORBA_Handler::instance_, + ACE_MT_CORBA_Handler, 0); + } + + return ACE_MT_CORBA_Handler::instance_; +} + +int +ACE_MT_CORBA_Handler::suspend (void) +{ + // Suspend the event handler listening for new CORBA requests to + // dispatch. + this->reactor_->suspend_handler (this->pipe_.read_handle ()); + + // Suspend the daemon thread. + this->thr_mgr ()->suspend_all (); + return 0; +} + +int +ACE_MT_CORBA_Handler::resume (void) +{ + // Resume the event handler listening for new CORBA requests to + // dispatch. + this->reactor_->resume_handler (this->pipe_.read_handle ()); + + // Resume the daemon thread. + this->thr_mgr ()->resume_all (); + return 0; +} + +ACE_MT_CORBA_Handler::ACE_MT_CORBA_Handler (void) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::ACE_MT_CORBA_Handler"); + this->thr_mgr (ACE_Service_Config::thr_mgr ()); + + int result = 0; + + if (this->pipe_.open () == -1) + result = -1; + // Register one end of the pipe with the reactor with a READ mask. + else if (this->reactor_->register_handler + (this->pipe_.read_handle (), this, ACE_Event_Handler::READ_MASK) == -1) + result = -1; + // Create a new thread that processes events for the Orbix event + // queue. + else if (this->thr_mgr ()->spawn (ACE_THR_FUNC (ACE_MT_CORBA_Handler::process_events), + 0, THR_DETACHED | THR_NEW_LWP) == -1) + result = -1; + + if (result == -1) + { + delete ACE_MT_CORBA_Handler::instance_; + ACE_MT_CORBA_Handler::instance_ = 0; + } +} + +void * +ACE_MT_CORBA_Handler::process_events (void *) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::process_events"); + + ACE_Thread_Control t (ACE_MT_CORBA_Handler::instance_->thr_mgr ()); + + // This thread only processes events. + TRY { + // it is OK to block + ACE_CORBA_1 (Orbix.processEvents) (ACE_CORBA_1 (Orbix.INFINITE_TIMEOUT), IT_X); + } CATCHANY { + // An error occured calling processEvents () - output the error. + cerr << IT_X << endl; + } ENDTRY; + + // Thread dies if we reach here : error occured in processEvents. + return 0; +} + +int +ACE_MT_CORBA_Handler::inRequestPreMarshal (ACE_CORBA_1 (Request) &req, + ACE_CORBA_1 (Environment) &IT_env) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::inRequestPreMarshal"); + + // Pump the request through the pipe. + u_long request_addr = (u_long) &req; + + ssize_t result = ACE::send (this->pipe_.write_handle (), + (const char *) &request_addr, + sizeof request_addr); + + if (result != sizeof request_addr) + { + // Don't continue with request + return 0; + } + + // Everything is fine: we have delegated the work to a different + // thread Tell Orbix we will dispatch the request later... + return -1; +} + +int +ACE_MT_CORBA_Handler::handle_input (ACE_HANDLE) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::handle_input"); + ACE_CORBA_1 (Request) *req = 0; + + u_long request_addr; + + // Read the request from the pipe. + ssize_t result = ACE::recv (this->pipe_.read_handle (), + (char *) &request_addr, + sizeof request_addr); + + if (result != sizeof request_addr) + // We are in trouble: bail out. + return -1; + + req = (ACE_CORBA_1 (Request) *) request_addr; + + // Tell Orbix to dispatch the request. + ACE_CORBA_1 (Orbix.continueThreadDispatch) (*req); + return 0; +} + +ACE_MT_CORBA_Handler::~ACE_MT_CORBA_Handler (void) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::~ACE_MT_CORBA_Handler"); + + // Unregister one end of the pipe with the reactor + this->reactor_->remove_handler + (this->pipe_.read_handle (), + ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + + this->pipe_.close (); + + ACE_MT_CORBA_Handler::instance_ = 0; +} +#endif /* ACE_HAS_MT_ORBIX */ +#endif /* ACE_HAS_ORBIX */ diff --git a/ace/CORBA_Handler.h b/ace/CORBA_Handler.h new file mode 100644 index 00000000000..4180600e85e --- /dev/null +++ b/ace/CORBA_Handler.h @@ -0,0 +1,238 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// CORBA_Handler.h +// +// = AUTHOR +// Douglas C. Schmidt (schmidt@cs.wustl.edu) and +// Irfan Pyarali (irfan@wuerl.wustl.edu). +// +// ============================================================================ + +#if !defined (_CORBA_HANDLER_H) +#define _CORBA_HANDLER_H + +#include "ace/Service_Config.h" +#include "ace/Pipe.h" + +#if defined (ACE_HAS_ORBIX) || defined (ACE_HAS_MT_ORBIX) +#define EXCEPTIONS +#define WANT_ORBIX_FDS +#include <CORBA.h> +// #include <daemon.hh> +#undef EXCEPTIONS +#undef WANT_ORBIX_FDS + +#if defined (ACE_WIN32) +#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 +#else +#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 +#endif /* ACE_WIN32 */ + +class ACE_Export ACE_CORBA_Handler : public ACE_Service_Object + // = TITLE + // Handle CORBA requests in conjunction with the ACE ACE_Reactor. + // Note, do *NOT* inherit from this class! Instead, use the + // ACE_MT_CORBA_HAndler and ACE_ST_CORBA_Handler as Singletons. +{ +public: + // = Activation and deactivation methods. + + virtual int activate_service (const char *service_name, + const char *marker_name = 0, + const char *service_location = 0); + // Activate and register <service_name> with the Orbix daemon. If + // <marker_name> and <service_location> are != 0 then do a "putit" + // to register this service with orbixd. This method also + // increments the reference count of active services using the + // ACE_ST_CORBA_Handler. + + virtual int deactivate_service (const char *service_name = 0, + const char *marker_name = 0); + // Decrement the reference count and free up all the + // resources if this is the last service to be using + // the ACE_ST_CORBA_Handler... + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + void reactor (ACE_Reactor *); + // Set the reactor instance. + + ACE_Reactor *reactor (void) ; + // Get the reactor instance. + +protected: + ACE_CORBA_Handler (void); + // Make this into an "abstract" class... + + virtual ~ACE_CORBA_Handler (void); + // Note virtual destructor... + + virtual int register_service (const char *service_name, + const char *marker_name, + const char *service_location); + // Register <service_name> by doing a "putit" to register + // the <service_name> using the <marker_name> at <service_location> + // with orbixd. + + virtual int remove_service (const char *service_name, + const char *marker_name = 0); + // Register <service_name> by doing a "putit" to register + // <service_name> using the <marker_name> with orbixd. + + ACE_Reactor *reactor_; + // Event demultiplexor used by ACE_ST_CORBA_Handler + + ssize_t reference_count_; + // Keep track of the number of active CORBA_Handlers. + +private: + // = Disallow assignment and initialization (this applies to derived + // classes, as well!) + ACE_CORBA_Handler (const ACE_CORBA_Handler &rhs); + const ACE_CORBA_Handler &operator= (const ACE_CORBA_Handler &rhs); +}; + +class ACE_Export ACE_ST_CORBA_Handler : public ACE_CORBA_Handler + // = TITLE + // Handle single-threaded CORBA requests in conjunction with the + // ACE_Reactor. +{ +public: + static ACE_CORBA_Handler *instance (void); + // Returns a Singleton. + + virtual int handle_input (ACE_HANDLE); + // Process the next Orbix event. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + // = The iterations are dictate how many processNextEvent() calls + // are run per-callback. + + size_t iterations (void); + // Get the current iteration. + + void iterations (size_t); + // Set the current iteration. + + // = Dynamic linking hooks. + virtual int suspend (void); + // Atomically suspend all the threads associated with the <thr_mgr ()>. + + virtual int resume (void); + // Atomically resume all the threads associated with the <thr_mgr ()_>. + +protected: + void get_orbix_descriptors (void); + // Preinitialize any descriptors that Orbix is using. This is + // called in instance (). + + ACE_ST_CORBA_Handler (void); + // Constructors (ensure Singleton...). + + virtual ~ACE_ST_CORBA_Handler (void); + // Destructor cleans up resources. + + static void insert_handle (ACE_HANDLE); + // Insert a descriptor into the ACE_Reactor that Orbix has just added. + + static void remove_handle (ACE_HANDLE); + // Remove a descriptor from the ACE_Reactor that Orbix has just deleted. + + static ACE_ST_CORBA_Handler *instance_; + // ACE_ST_CORBA_Handler is a singleton object. + + size_t iterations_; + // Number of iterations to process per processNextEvent() call. +}; + +#if defined (ACE_HAS_MT_ORBIX) + +class ACE_Export ACE_MT_CORBA_Handler : public ACE_CORBA_Handler, public ACE_CORBA_1 (ThreadFilter) + // = TITLE + // Handle multi-threaded CORBA requests in conjunction with the + // ACE Reactor. +{ +public: + static ACE_CORBA_Handler *instance (void); + // Returns a Singleton. + + virtual int handle_input (ACE_HANDLE); + // Process the next Orbix event. + + void thr_mgr (ACE_Thread_Manager *tm); + // Set the Thread_Manager used by ACE_MT_CORBA_Handler + + ACE_Thread_Manager *thr_mgr (void) const; + // Get the Thread_Manager used by ACE_MT_CORBA_Handler + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + // = Dynamic linking hooks. + virtual int suspend (void); + // Atomically suspend all the threads associated with the <thr_mgr ()>. + + virtual int resume (void); + // Atomically resume all the threads associated with the <thr_mgr ()>. + +protected: + static void *process_events (void *); + // function executed by new thread + + ACE_MT_CORBA_Handler (void); + // Constructors (ensure Singleton...). + + virtual ~ACE_MT_CORBA_Handler (void); + // Destructor cleans up resources. + + virtual int inRequestPreMarshal (ACE_CORBA_1 (Request) &r, + ACE_CORBA_1 (Environment) &IT_env = ACE_CORBA_1 (default_environment)); + // Take the incoming request and pass it to this->handle_input() but + // through the Reactor. + + static ACE_MT_CORBA_Handler *instance_; + // ACE_MT_CORBA_Handler is a singleton object. + + ACE_Thread_Manager *thr_mgr_; + // Event demultiplexor used by ACE_ST_CORBA_Handler. + + ACE_Pipe pipe_; + // Used to send CORBA::Requests through the server + +#if defined (ACE_MT_SAFE) + static ACE_Thread_Mutex ace_mt_corba_handler_lock_; + // Double-Check lock. +#endif /* ACE_MT_SAFE */ +}; +#endif /* ACE_HAS_MT_ORBIX */ + +#if defined (__INLINE__) +#include "ace/CORBA_Handler.i" +#endif /* __INLINE__ */ + +#endif /* ACE_HAS_ORBIX */ +#endif /* ACE_CORBA_HANDLER_H */ diff --git a/ace/CORBA_Handler.i b/ace/CORBA_Handler.i new file mode 100644 index 00000000000..794b6da5d09 --- /dev/null +++ b/ace/CORBA_Handler.i @@ -0,0 +1,56 @@ +/* -*- C++ -*- */ +// $Id$ + +// CORBA_Handler.i + +#if defined (ACE_HAS_ORBIX) +// = Set/get the number of iterations per processNextEvent() call. + +/* static */ +ACE_INLINE size_t +ACE_ST_CORBA_Handler::iterations (void) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::iterations"); + return this->iterations_; +} + +/* static */ +ACE_INLINE void +ACE_ST_CORBA_Handler::iterations (size_t i) +{ + ACE_TRACE ("ACE_ST_CORBA_Handler::iterations"); + this->iterations_ = i; +} + +/* static */ +ACE_INLINE void +ACE_CORBA_Handler::reactor (ACE_Reactor *reactor) +{ + ACE_TRACE ("ACE_CORBA_Handler::reactor"); + this->reactor_ = reactor; +} + +/* static */ +ACE_INLINE ACE_Reactor * +ACE_CORBA_Handler::reactor (void) +{ + ACE_TRACE ("ACE_CORBA_Handler::reactor"); + return this->reactor_; +} + +#if defined (ACE_HAS_MT_ORBIX) +ACE_INLINE void +ACE_MT_CORBA_Handler::thr_mgr (ACE_Thread_Manager *tm) +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::thr_mgr"); + this->thr_mgr_ = tm; +} + +ACE_INLINE ACE_Thread_Manager * +ACE_MT_CORBA_Handler::thr_mgr (void) const +{ + ACE_TRACE ("ACE_MT_CORBA_Handler::thr_mgr"); + return this->thr_mgr_; +} +#endif /* ACE_HAS_MT_ORBIX */ +#endif /* ACE_HAS_ORBIX */ diff --git a/ace/CORBA_Ref.cpp b/ace/CORBA_Ref.cpp new file mode 100644 index 00000000000..5bfec4317ae --- /dev/null +++ b/ace/CORBA_Ref.cpp @@ -0,0 +1,86 @@ +// CORBA_Ref.cpp +// $Id$ + +#if !defined (ACE_CORBA_REF_C) +#define ACE_CORBA_REF_C + +#define ACE_BUILD_DLL +#include "ace/CORBA_Ref.h" + +#if !defined (__ACE_INLINE__) +#include "ace/CORBA_Ref.i" +#endif /* __ACE_INLINE__ */ + +template<class CORBA_REF> +ACE_CORBA_Ref<CORBA_REF>::ACE_CORBA_Ref (void) + : ref_ (0) +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::ACE_CORBA_Ref"); +} + +template<class CORBA_REF> +ACE_CORBA_Ref<CORBA_REF>::ACE_CORBA_Ref (CORBA_REF *ref) +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::ACE_CORBA_Ref"); + if (ref != 0) + ref_ = ref->_duplicate (); + else + ref_ = 0; +} + +template<class CORBA_REF> CORBA_REF * +ACE_CORBA_Ref<CORBA_REF>::operator= (CORBA_REF *ref) +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::operator="); + if (ref_ != 0) + ref_->_release (); + if (ref == 0) + { + ref_ = 0; + return 0; + } + else + return ref_ = ref->_duplicate (); +} + +template<class CORBA_REF> +ACE_CORBA_Ref<CORBA_REF>::operator CORBA_REF * (void) const +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::operator CORBA_REF *"); + ACE_ASSERT (ref_ != 0); + return ref_; +} + +template<class CORBA_REF> CORBA_REF * +ACE_CORBA_Ref<CORBA_REF>::operator-> (void) const +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::operator->"); + ACE_ASSERT (ref_ != 0); + return ref_; +} + +template<class CORBA_REF> int +ACE_CORBA_Ref<CORBA_REF>::operator== (CORBA_REF *rhs) const +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::operator=="); + // pointer comparison. + return ref_ == rhs; +} + +template<class CORBA_REF> int +ACE_CORBA_Ref<CORBA_REF>::operator!= (CORBA_REF *rhs) const +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::operator!="); + // pointer comparison. + return ref_ != rhs; +} + +template<class CORBA_REF> +ACE_CORBA_Ref<CORBA_REF>::~ACE_CORBA_Ref () +{ + ACE_TRACE ("ACE_CORBA_Ref<CORBA_REF>::~ACE_CORBA_Ref"); + if (ref_ != 0) + ref_->_release (); +} + +#endif // ACE_CORBA_REF_C diff --git a/ace/CORBA_Ref.h b/ace/CORBA_Ref.h new file mode 100644 index 00000000000..c344cc401c6 --- /dev/null +++ b/ace/CORBA_Ref.h @@ -0,0 +1,80 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// CORBA_Ref +// +// = AUTHOR +// Irfan Pyarali (irfan@wuerl.wustl.edu). +// Tim Harrison (harrison@cs.wustl.edu) +// +// = DESCRIPTION +// A wrapper for helping with Orbix object references. +// +// ============================================================================ + +#if !defined (ACE_CORBA_REF_H) +#define ACE_CORBA_REF_H + +template <class CORBA_REF> +class ACE_CORBA_Ref + // = TITLE + // A wrapper for helping with orbix object references. + // + // = DESCRIPTION + // ACE_CORBA_Ref is parameterized by the type of orbix object + // reference to be used. The construtor, operator=, and the + // destructor of ACE_CORBA_Ref perform implicit duplicates and + // releases in order to help make the use of orbix object + // references transparent. +{ +public: + ACE_CORBA_Ref (void); + // Null construction. + + ACE_CORBA_Ref (CORBA_REF *ref); + // Contruction with an orbix ref. + // performs a ref->_duplicate(). + + CORBA_REF *operator= (CORBA_REF *ref); + // Assignment performs a ref->_duplicate(). + + operator CORBA_REF *(void) const; + // Type operator + + CORBA_REF *operator-> (void) const; + // Smart pointer to forward all CORBA_REF calls to the underlying + // orbix reference. + + int operator== (CORBA_REF *) const; + // Pointer comparison. + + int operator!= (CORBA_REF *) const; + // Pointer comparison. + + ~ACE_CORBA_Ref (void); + // Destruction: calls ref_->_release + +private: + CORBA_REF *ref_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/CORBA_Ref.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/CORBA_Ref.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("CORBA_Ref.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* CORBA_REF_H */ diff --git a/ace/CORBA_Ref.i b/ace/CORBA_Ref.i new file mode 100644 index 00000000000..3002ddac574 --- /dev/null +++ b/ace/CORBA_Ref.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// CORBA_Ref.i diff --git a/ace/Connector.cpp b/ace/Connector.cpp new file mode 100644 index 00000000000..917c6ce9ada --- /dev/null +++ b/ace/Connector.cpp @@ -0,0 +1,533 @@ +// Connector.cpp +// $Id$ + +#if !defined (ACE_CONNECTOR_C) +#define ACE_CONNECTOR_C + +#define ACE_BUILD_DLL +#include "ace/Connector.h" + +/* Shorthand names */ +#define SH SVC_HANDLER +#define PR_CO_1 ACE_PEER_CONNECTOR_1 +#define PR_CO_2 ACE_PEER_CONNECTOR_2 +#define PR_AD ACE_PEER_CONNECTOR_ADDR + +ACE_ALLOC_HOOK_DEFINE(ACE_Connector) + +template <class SH, PR_CO_1> ACE_Reactor * +ACE_Connector<SH, PR_CO_2>::reactor (void) const +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::reactor"); + return this->reactor_; +} + +template <class SH, PR_CO_1> void +ACE_Connector<SH, PR_CO_2>::reactor (ACE_Reactor *r) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::reactor"); + this->reactor_ = r; +} + +template <class SH, PR_CO_1> void +ACE_Connector<SH, PR_CO_2>::dump (void) const +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->handler_map_.dump (); + this->connector_.dump (); + ACE_DEBUG ((LM_DEBUG, "reactor_ = %x", this->reactor_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::activate_svc_handler (SVC_HANDLER *svc_handler) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::activate_svc_handler"); + // We are connected now, so try to open things up. + if (svc_handler->open ((void *) this) == -1) + { + // Make sure to close down the Channel to avoid descriptor leaks. + svc_handler->close (0); + return -1; + } + else + return 0; +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::connect_svc_handler (SVC_HANDLER *svc_handler, + const PR_AD &remote_addr, + const ACE_Synch_Options &synch_options, + const PR_AD &local_addr, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::connect_svc_handler"); + // Note that if timeout == ACE_Time_Value (x, y) where (x > 0 || y > + // 0) then this->connector_.connect() will block synchronously. If + // <use_reactor> is set then we don't want this to happen (since we + // want the ACE_Reactor to do the timeout asynchronously). + // Therefore, we'll force this->connector_ to use ACE_Time_Value (0, + // 0) in this case... + + ACE_Time_Value *timeout; + int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR]; + + if (use_reactor) + timeout = (ACE_Time_Value *) &ACE_Time_Value::zero; + else + timeout = (ACE_Time_Value *) synch_options.time_value (); + + if (this->connector_.connect (*svc_handler, + remote_addr, + timeout, + local_addr, + reuse_addr, + flags, + perms) == -1) + { + if (use_reactor && errno == EWOULDBLOCK) + { + // If the connection hasn't completed and we are using + // non-blocking semantics then register ourselves with the + // ACE_Reactor so that it will call us back when the + // connection is complete or we timeout, whichever comes + // first... Note that we needn't check the return value + // here because if something goes wrong that will reset + // errno this will be detected by the caller (since -1 is + // being returned...). + this->create_AST (svc_handler, synch_options); + } + else + // Make sure to close down the Channel to avoid descriptor leaks. + svc_handler->close (0); + return -1; + } + else + // Activate immediately if we are connected. + return this->activate_svc_handler (svc_handler); +} + +template <class SH, PR_CO_1> PEER_CONNECTOR & +ACE_Connector<SH, PR_CO_2>::connector (void) const +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::connector"); + return (PEER_CONNECTOR &) this->connector_; +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::open (ACE_Reactor *reactor) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::open"); + this->reactor_ = reactor; + return 0; +} + +// Register the SVC_HANDLER with the map of pending connections so +// that it can be activated when the connection completes. + +template <class SH, PR_CO_1> ACE_HANDLE +ACE_Connector<SH, PR_CO_2>::get_handle (void) const +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::get_handle"); + return this->connector_.get_handle (); +} + +template <class SH> +ACE_Svc_Tuple<SH>::ACE_Svc_Tuple (SVC_HANDLER *sh, + ACE_HANDLE handle, + const void *arg, + int id) + : svc_handler_ (sh), + handle_ (handle), + arg_ (arg), + cancellation_id_ (id) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::ACE_Svc_Tuple"); +} + +template <class SH> SVC_HANDLER * +ACE_Svc_Tuple<SH>::svc_handler (void) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::svc_handler"); + return this->svc_handler_; +} + +template <class SH> const void * +ACE_Svc_Tuple<SH>::arg (void) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::arg"); + return this->arg_; +} + +template <class SH> void +ACE_Svc_Tuple<SH>::arg (const void *v) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::arg"); + this->arg_ = v; +} + +template <class SH> ACE_HANDLE +ACE_Svc_Tuple<SH>::handle (void) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::handle"); + return this->handle_; +} + +template <class SH> void +ACE_Svc_Tuple<SH>::handle (ACE_HANDLE h) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::handle"); + this->handle_ = h; +} + +template <class SH> int +ACE_Svc_Tuple<SH>::cancellation_id (void) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::cancellation_id"); + return this->cancellation_id_; +} + +template <class SH> void +ACE_Svc_Tuple<SH>::cancellation_id (int id) +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::cancellation_id"); + this->cancellation_id_ = id; +} + +template <class SH> void +ACE_Svc_Tuple<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Svc_Tuple<SH>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "svc_handler_ = %x", this->svc_handler_)); + ACE_DEBUG ((LM_DEBUG, "\narg_ = %x", this->arg_)); + ACE_DEBUG ((LM_DEBUG, "\ncancellation_id_ = %d", this->cancellation_id_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SH, PR_CO_1> +ACE_Connector<SH, PR_CO_2>::ACE_Connector (ACE_Reactor *reactor) + : reactor_ (reactor) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::ACE_Connector"); +} + +// This method is called if a connection times out before completing. +// In this case, we call our cleanup_AST() method to cleanup the +// descriptor from the ACE_Connector's table. + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::handle_timeout (const ACE_Time_Value &tv, + const void *arg) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::handle_timeout"); + AST *ast = 0; + + if (this->cleanup_AST (((AST *) arg)->handle (), + ast) == -1) + return -1; + else + { + ACE_ASSERT (((AST *) arg) == ast); + + // We may need this seemingly unnecessary assignment to work + // around a bug with MSVC++? + SH *sh = ast->svc_handler (); + + // Forward to the SVC_HANDLER the <arg> that was passed in as a + // magic cookie during ACE_Connector::connect(). + sh->handle_timeout (tv, ast->arg ()); + + delete ast; + return 0; + } +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::cleanup_AST (ACE_HANDLE handle, + ACE_Svc_Tuple<SH> *&ast) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::cleanup_AST"); + + // Locate the ACE_Svc_Handler corresponding to the socket descriptor. + if (this->handler_map_.find (handle, ast) == -1) + { + // Error, entry not found in map. + errno = ENOENT; + ACE_ERROR_RETURN ((LM_ERROR, "%p %d not found in map\n", + "find", handle), -1); + } + + // Try to remove from ACE_Timer_Queue but if it's not there we ignore + // the error. + this->reactor_->cancel_timer (ast->cancellation_id ()); + + // Remove ACE_HANDLE from ACE_Reactor. + this->reactor_->remove_handler (handle, ACE_Event_Handler::RWE_MASK + | ACE_Event_Handler::DONT_CALL); + + // Remove ACE_HANDLE from the map. + this->handler_map_.unbind (handle); + return 0; +} + +// Called when a failure occurs during asynchronous connection +// establishment. Simply delegate all work to this->handle_output(). + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::handle_input (ACE_HANDLE h) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::handle_input"); + AST *ast = 0; + + if (this->cleanup_AST (h, ast) != -1) + { + ast->svc_handler ()->close (0); + delete ast; + } + return 0; // Already removed from the ACE_Reactor. +} + +// Finalize a connection established in non-blocking mode. When a +// non-blocking connect *succeeds* the descriptor becomes enabled for +// writing... Likewise, it is generally the case that when a +// non-blocking connect *fails* the descriptor becomes enabled for +// reading. + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::handle_output (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::handle_output"); + AST *ast = 0; + + if (this->cleanup_AST (handle, ast) == -1) + return 0; + + ACE_ASSERT (ast != 0); // This shouldn't happen! + + // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER. + ast->svc_handler ()->set_handle (handle); + + PR_AD raddr; + + // Check to see if we're connected. + if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1) + this->activate_svc_handler (ast->svc_handler ()); + else // Somethings gone wrong, so close down... + ast->svc_handler ()->close (0); + + delete ast; + return 0; +} + +// Initiate connection to peer. + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::connect (SH *sh, + const PR_AD &remote_addr, + const ACE_Synch_Options &synch_options, + const PR_AD &local_addr, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::connect"); + // Delegate to connection strategy. + return this->connect_svc_handler (sh, remote_addr, synch_options, + local_addr, reuse_addr, + flags, perms); + +} + +// Cancel a <svc_handler> that was started asynchronously. +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::cancel (SH *sh) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::cancel"); + MAP_ITERATOR mi (this->handler_map_); + + for (MAP_ENTRY *me = 0; + mi.next (me) != 0; + mi.advance ()) + if (me->int_id_->svc_handler () == sh) + { + AST *ast = 0; + this->cleanup_AST (me->ext_id_, ast); + ACE_ASSERT (ast == me->int_id_); + delete me->int_id_; + return 0; + } + + return -1; +} + +// Register the pending SVC_HANDLER with the map so that it can be +// activated later on when the connection complets. + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::create_AST (SH *sh, + const ACE_Synch_Options &synch_options) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::create_AST"); + AST *ast; + + ACE_NEW_RETURN (ast, AST (sh, this->get_handle (), synch_options.arg ()), -1); + + // Register this with the reactor for both reading and writing + // events. + if (this->reactor_->register_handler (this, + ACE_Event_Handler::READ_MASK + | ACE_Event_Handler::WRITE_MASK) == -1) + goto fail1; + + // Bind ACE_Svc_Tuple with the ACE_HANDLE we're trying to connect. + else if (this->handler_map_.bind (this->get_handle (), ast) == -1) + goto fail2; + // If we're starting connection under timer control then we need to + // schedule a timeout with the ACE_Reactor. + else + { + ACE_Time_Value *tv = (ACE_Time_Value *) synch_options.time_value (); + + if (tv != 0) + { + int cancellation_id = + this->reactor_->schedule_timer (this, + (const void *) ast, + *tv); + if (cancellation_id == -1) + goto fail3; + + ast->cancellation_id (cancellation_id); + return 0; + } + else + { + // Reset this because something might have gone wrong + // elsewhere... + errno = EWOULDBLOCK; + return 0; // Ok, everything worked just fine... + } + } + + // Undo previous actions using the ol' "goto label and fallthru" + // trick... +fail3: + this->handler_map_.unbind (this->get_handle ()); + /* FALLTHRU */ +fail2: + this->reactor_->remove_handler (this, + ACE_Event_Handler::READ_MASK + | ACE_Event_Handler::WRITE_MASK + | ACE_Event_Handler::DONT_CALL); + /* FALLTHRU */ +fail1: + delete ast; + return -1; +} + +// Terminate the Client ACE_Connector by iterating over any +// unconnected ACE_Svc_Handler's and removing them from the +// ACE_Reactor. Note that we can't call handle_close() back at this +// point since we own these things and we'll just get called +// recursively! + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::handle_close (ACE_HANDLE, ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::handle_close"); + // Remove all timer objects from the Reactor's Timer_Queue. + this->reactor_->cancel_timer (this); + + MAP_ITERATOR mi (this->handler_map_); + + // Iterate through the map and shut down all the pending handlers. + + for (MAP_ENTRY *me = 0; + mi.next (me) != 0; + mi.advance ()) + { + this->reactor_->remove_handler (me->ext_id_, + mask | ACE_Event_Handler::DONT_CALL); + + AST *ast = 0; + this->cleanup_AST (me->ext_id_, ast); + ACE_ASSERT (ast == me->int_id_); + delete me->int_id_; + } + return 0; +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::fini (void) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::fini"); + // Make sure we call our handle_close(), not a subclass's! + return ACE_Connector<SH, PR_CO_2>::handle_close (); +} + +// Hook called by the explicit dynamic linking facility. + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::init"); + return -1; +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::suspend (void) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::suspend"); + return -1; +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::resume (void) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::resume"); + return -1; +} + +template <class SH, PR_CO_1> int +ACE_Connector<SH, PR_CO_2>::info (char **strp, size_t length) const +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::info"); + char buf[BUFSIZ]; + char addr_str[BUFSIZ]; + PR_AD addr; + + if (this->connector ().get_local_addr (addr) == -1) + return -1; + else if (addr.addr_to_string (addr_str, sizeof addr) == -1) + return -1; + + ACE_OS::sprintf (buf, "%s\t %s %s", + "ACE_Connector", addr_str, "# connector factory\n"); + + if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, buf, length); + return ACE_OS::strlen (buf); +} + +template <class SH, PR_CO_1> +ACE_Connector<SH, PR_CO_2>::~ACE_Connector (void) +{ + ACE_TRACE ("ACE_Connector<SH, PR_CO_2>::~ACE_Connector"); + // We will call our handle_close(), not a subclass's, due to the way + // that C++ destructors work. + this->handle_close (); +} + +#undef SH +#undef PR_CO_1 +#undef PR_CO_2 +#undef PR_AD +#endif /* ACE_CONNECTOR_C */ diff --git a/ace/Connector.h b/ace/Connector.h new file mode 100644 index 00000000000..8d9e7d44a5c --- /dev/null +++ b/ace/Connector.h @@ -0,0 +1,279 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Connector.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_CONNECTOR_H) +#define ACE_CONNECTOR_H + +#include "ace/Service_Config.h" +#include "ace/Service_Object.h" +#include "ace/Timer_Queue.h" +#include "ace/Map_Manager.h" +#include "ace/Svc_Handler.h" +#include "ace/Strategies.h" + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +#define ACE_PEER_CONNECTOR_1 class PEER_CONNECTOR +#define ACE_PEER_CONNECTOR_2 PEER_CONNECTOR +#define ACE_PEER_CONNECTOR PEER_CONNECTOR +#define ACE_PEER_CONNECTOR_ADDR PEER_CONNECTOR::PEER_ADDR +#else +#define ACE_PEER_CONNECTOR_1 class PEER_CONNECTOR, class PEER_ADDR +#define ACE_PEER_CONNECTOR_2 PEER_CONNECTOR, PEER_ADDR +#define ACE_PEER_CONNECTOR PEER_CONNECTOR +#define ACE_PEER_CONNECTOR_ADDR PEER_ADDR +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +template <class SVC_HANDLER> +class ACE_Svc_Tuple + // = TITLE + // Holds the ACE_Svc_Handler and its argument and + // <ACE_Timer_Handle> until an asynchronous connection completes. + // + // = DESCRIPTION + // This is a no-brainer... +{ +public: + // = Initialization methods. + ACE_Svc_Tuple (SVC_HANDLER *, + ACE_HANDLE, + const void * = 0, + int timer_id = 0); + + // = Get SVC_HANDLER. + SVC_HANDLER *svc_handler (void); + + // = Get/set handle. + ACE_HANDLE handle (void); + // Get handle. + void handle (ACE_HANDLE); + // Set handle. + + // = Get/set argument. + const void *arg (void); + // Get argument. + void arg (const void *); + // Set argument. + + // = Set/get cancellation handle. + int cancellation_id (void); + // Get cancellation id. + void cancellation_id (int timer_id); + // Set cancellation id. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + SVC_HANDLER *svc_handler_; + // Associated SVC_HANDLER. + + ACE_HANDLE handle_; + // IPC <HANDLE> that we are trying to connect. + + const void *arg_; + // Associated argument. + + int cancellation_id_; + // Associated cancellation id. +}; + +template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> +class ACE_Connector : public ACE_Service_Object + // = TITLE + // Generic factory for actively connecting clients and creating + // service handlers (SVC_HANDLERs). + // + // = DESCRIPTION + // Implements the strategy for actively establishing connections + // with clients. An ACE_Connector is parameterized by concrete + // types that conform to the interfaces of PEER_CONNECTOR and + // SVC_HANDLER. The PEER_CONNECTOR is instantiated with a + // transport mechanism that passively establishes connections. + // The SVC_HANDLER is instantiated with a concrete type that + // performs the application-specific service. An ACE_Connector + // inherits from ACE_Service_Object, which in turn inherits from + // ACE_Event_Handler. This enables the ACE_Reactor to dispatch + // the ACE_Connector's handle_output method when connections + // complete asynchronously. The handle_output method performs + // the connector's active connection establishment and service + // activation strategy. +{ +public: + // = Initialization and termination methods. + + ACE_Connector (ACE_Reactor *r = ACE_Service_Config::reactor ()); + // Initialize a connector. + + virtual int open (ACE_Reactor *r = ACE_Service_Config::reactor ()); + // Initialize a connector. + + ~ACE_Connector (void); + // Shutdown a connector and release resources. + + // = Connection establishment method + + virtual int connect (SVC_HANDLER *svc_handler, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, + const ACE_PEER_CONNECTOR_ADDR &local_addr + = (ACE_PEER_CONNECTOR_ADDR &) ACE_PEER_CONNECTOR_ADDR::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Initiate connection to <peer> at <remote_addr> using + // <synch_options>. If the caller wants to designate the selected + // <local_addr> they can (and can also insist that the <local_addr> + // be reused by passing a value <reuse_addr> == 1). <flags> and + // <perms> can be used to pass any flags that are needed to perform + // specific operations such as opening a file within connect with + // certain permissions. + + virtual int cancel (SVC_HANDLER *svc_handler); + // Cancel a <svc_handler> that was started asynchronously. + + ACE_PEER_CONNECTOR &connector (void) const; + // Return the underlying PEER_CONNECTOR object. + + ACE_Reactor *reactor (void) const; + // Get the underlying Reactor *. + + void reactor (ACE_Reactor *); + // Set the underlying Reactor *. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Helpful typedefs. + + typedef ACE_Svc_Tuple<SVC_HANDLER> AST; + +#if defined (ACE_MT_SAFE) + typedef ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_RW_Mutex> MAP_MANAGER; + typedef ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_RW_Mutex> MAP_ITERATOR; + typedef ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *> MAP_ENTRY; +// ACE_Thread_Mutex lock_; +#else + typedef ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_Null_Mutex> MAP_MANAGER; + typedef ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_Null_Mutex> MAP_ITERATOR; + typedef ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *> MAP_ENTRY; +#endif /* ACE_MT_SAFE */ + + // = The following two methods define the Connector's strategies for + // connecting and activating SVC_HANDLER's, respectively. + + virtual int connect_svc_handler (SVC_HANDLER *svc_handler, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + const ACE_Synch_Options &synch_options, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms); + // Bridge method for connecting the <svc_handler> to the + // <remote_addr>. The default behavior delegates to the + // PEER_CONNECTOR::connect. + + virtual int activate_svc_handler (SVC_HANDLER *svc_handler); + // Bridge method for activating a <svc_handler> with the appropriate + // concurrency strategy. The default behavior of this method is to + // activate the SVC_HANDLER by calling its open() method (which + // allows the SVC_HANDLER to define its own concurrency strategy). + // However, subclasses can override this strategy to do more + // sophisticated concurrency activations (such as creating the + // SVC_HANDLER as an "active object" via multi-threading or + // multi-processing). + + virtual int handle_input (ACE_HANDLE); + // Called by ACE_Reactor when asynchronous connections fail. + + virtual int handle_output (ACE_HANDLE); + // Called by ACE_Reactor when asynchronous connections succeed. + + // = Dynamic linking hooks. + virtual int init (int argc, char *argv[]); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int fini (void); + // Calls <handle_close> to shutdown the Connector gracefully. + + virtual int info (char **, size_t) const; + // Default version returns address info in <buf>. + + // = Demultiplexing hooks. + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::RWE_MASK); + // Terminate the Client ACE_Connector by iterating over any + // unconnected ACE_Svc_Handler's and removing them from the + // ACE_Reactor. + + virtual ACE_HANDLE get_handle (void) const; + // Return the underlying handle that's associated with the + // SVC_HANDLER we're currently trying to connect (or + // ACE_INVALID_HANDLER if there isn't one). + + virtual int handle_timeout (const ACE_Time_Value &tv, + const void *arg); + // This method is called if a connection times out before + // completing. + + // = Service management hooks. + virtual int suspend (void); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int resume (void); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + int create_AST (SVC_HANDLER *, + const ACE_Synch_Options &); + // Creates and inserts an ACE_Svc_Tuple into the <handler_map_>. + // so that we can continue accepting this connection asynchronously. + + int cleanup_AST (ACE_HANDLE, AST *&); + // Cleanup the <handler_map_> and returns the appropriate + // ACE_Svc_Tuple (which is 0 if there is no associated tuple). + + MAP_MANAGER handler_map_; + // Lookup table that maps an I/O handle to a SVC_HANDLER *. + +private: + ACE_PEER_CONNECTOR connector_; + // Factor that establishes connections actively. + + ACE_Reactor *reactor_; + // Event demultiplex associated with this object. +}; + +#include "ace/Connector.i" + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Connector.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Connector.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_CONNECTOR_H */ diff --git a/ace/Connector.i b/ace/Connector.i new file mode 100644 index 00000000000..7c7afcc0184 --- /dev/null +++ b/ace/Connector.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Connector.i diff --git a/ace/DEV.cpp b/ace/DEV.cpp new file mode 100644 index 00000000000..6adf55737d5 --- /dev/null +++ b/ace/DEV.cpp @@ -0,0 +1,54 @@ +// DEV.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/DEV.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_DEV) + +void +ACE_DEV::dump (void) const +{ + ACE_TRACE ("ACE_DEV::dump"); +} + +// Return the local endpoint address. + +int +ACE_DEV::get_local_addr (ACE_DEV_Addr &addr) const +{ + ACE_TRACE ("ACE_DEV::get_local_addr"); + + addr = this->addr_; + return 0; +} + +// Return the address of the remotely connected peer (if there is +// one). + +int +ACE_DEV::get_remote_addr (ACE_DEV_Addr &addr) const +{ + ACE_TRACE ("ACE_DEV::get_remote_addr"); + addr = this->addr_; + return 0; +} + +// This is the do-nothing constructor. + +ACE_DEV::ACE_DEV (void) +{ + ACE_TRACE ("ACE_DEV::ACE_DEV"); +} + +// Close the device + +int +ACE_DEV::close (void) +{ + ACE_TRACE ("ACE_DEV::close"); + int result = ACE_OS::close (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + return result; +} diff --git a/ace/DEV.h b/ace/DEV.h new file mode 100644 index 00000000000..4d4cdd0ace8 --- /dev/null +++ b/ace/DEV.h @@ -0,0 +1,71 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// DEV.h +// +// = AUTHOR +// Gerhard Lenzer +// +// ============================================================================ + +#if !defined (ACE_DEV_H) +#define ACE_DEV_H + +#include "ace/IO_SAP.h" +#include "ace/DEV_Addr.h" + +// 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) +#define ACE_DEV_CONNECTOR ACE_DEV_Connector +#define ACE_DEV_STREAM ACE_DEV_Stream +#else /* TEMPLATES are broken (must be a cfront-based compiler...) */ +#define ACE_DEV_CONNECTOR ACE_DEV_Connector, ACE_DEV_Addr +#define ACE_DEV_STREAM ACE_DEV_Stream, ACE_DEV_Addr +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +class ACE_Export ACE_DEV : public ACE_IO_SAP + // = TITLE + // Defines the member functions for the base class of the + // ACE_DEV abstraction. +{ +public: + int close (void); + // Close down the DEVICE + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + // = The following two methods are no-ops to keep the + // <ACE_Connector> happy. + int get_local_addr (ACE_DEV_Addr &) const; + // Return the local endpoint address. + + int get_remote_addr (ACE_DEV_Addr &) const; + // Return the address of the remotely connected peer (if there is + // one). + +protected: + ACE_DEV (void); + // Ensure that this class is an abstract base class + + ACE_DEV_Addr addr_; + // Address of device we are connected to. +}; + +#include "ace/DEV.i" + +#endif /* ACE_DEV_H */ diff --git a/ace/DEV.i b/ace/DEV.i new file mode 100644 index 00000000000..86d5e6b511d --- /dev/null +++ b/ace/DEV.i @@ -0,0 +1,6 @@ +/* -*- C++ -*- */ +// $Id$ + +// DEV.i + + diff --git a/ace/DEV_Addr.cpp b/ace/DEV_Addr.cpp new file mode 100644 index 00000000000..01833806e62 --- /dev/null +++ b/ace/DEV_Addr.cpp @@ -0,0 +1,65 @@ +// DEV_Addr.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/DEV_Addr.h" + +#if !defined (__ACE_INLINE__) +#include "ace/DEV_Addr.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_DEV_Addr) + +void +ACE_DEV_Addr::dump (void) const +{ + ACE_TRACE ("ACE_DEV_Addr::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "devname_ = %s", this->devname_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Do nothing constructor. + +ACE_DEV_Addr::ACE_DEV_Addr (void) + : ACE_Addr (AF_DEV, sizeof this->devname_) +{ + ACE_TRACE ("ACE_DEV_Addr::ACE_DEV_Addr"); + + (void) ACE_OS::memset ((void *) &this->devname_, + 0, sizeof this->devname_); +} + +// Copy constructor. + +ACE_DEV_Addr::ACE_DEV_Addr (const ACE_DEV_Addr &sa) + : ACE_Addr (AF_DEV, ACE_OS::strlen (this->devname_)) +{ + ACE_TRACE ("ACE_DEV_Addr::ACE_DEV_Addr"); + + (void) ACE_OS::memcpy ((void *) &this->devname_, + (void *) &sa.devname_, + sa.get_size ()); +} + +ACE_DEV_Addr::ACE_DEV_Addr (LPCTSTR devname) +{ + ACE_TRACE ("ACE_DEV_Addr::ACE_DEV_Addr"); + + this->set (devname); +} + +ACE_DEV_Addr & +ACE_DEV_Addr::operator= (const ACE_DEV_Addr &sa) +{ + ACE_TRACE ("ACE_DEV_Addr::operator="); + + if (this != &sa) + (void) ACE_OS::memcpy ((void *) &this->devname_, + (void *) &sa.devname_, + sa.get_size ()); + return *this; +} + diff --git a/ace/DEV_Addr.h b/ace/DEV_Addr.h new file mode 100644 index 00000000000..1a00dc166f9 --- /dev/null +++ b/ace/DEV_Addr.h @@ -0,0 +1,75 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// DEV_Addr.h +// +// = AUTHOR +// Gerhard Lenzer and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_DEV_ADDR_H) +#define ACE_DEV_ADDR_H + +#include "ace/Addr.h" +#include "ace/ACE.h" + +class ACE_Export ACE_DEV_Addr : public ACE_Addr + // = TITLE + // Defines device address family address format. +{ +public: + // = Initialization methods. + ACE_DEV_Addr (void); + // Default constructor. + + ACE_DEV_Addr (const ACE_DEV_Addr &sa); + // Copy constructor. + + ACE_DEV_Addr (LPCTSTR devname); + // Create a ACE_DEV_Addr from a device name. + + void set (LPCTSTR devname); + // Create a ACE_Addr from a ACE_DEV pathname. + + ACE_DEV_Addr &operator= (const ACE_DEV_Addr &); + // Assignment operator. + + virtual void *get_addr (void) const; + // Return a pointer to the address. + + virtual int addr_to_string (char addr[], size_t) const; + // Transform the current address into string format. + + virtual int operator == (const ACE_Addr &SAP) const; + // Compare two addresses for equality. + + virtual int operator != (const ACE_Addr &SAP) const; + // Compare two addresses for inequality. + + LPCTSTR get_path_name (void) const; + // Return the path name used for the rendezvous point. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + TCHAR devname_[MAXNAMLEN + 1]; + // Name of the device. +}; + +#if defined (__ACE_INLINE__) +#include "ace/DEV_Addr.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_DEV_ADDR_H */ diff --git a/ace/DEV_Addr.i b/ace/DEV_Addr.i new file mode 100644 index 00000000000..4507b0da782 --- /dev/null +++ b/ace/DEV_Addr.i @@ -0,0 +1,65 @@ +/* -*- C++ -*- */ +// $Id$ + + +ACE_INLINE void +ACE_DEV_Addr::set (LPCTSTR devname) +{ + ACE_TRACE ("ACE_DEV_Addr::set"); + + this->ACE_Addr::base_set (AF_DEV, ACE_OS::strlen (devname)); + ACE_OS::strncpy (this->devname_, devname, MAXNAMLEN); +} + +// Transform the current address into string format. + +ACE_INLINE int +ACE_DEV_Addr::addr_to_string (char s[], size_t len) const +{ + ACE_TRACE ("ACE_DEV_Addr::addr_to_string"); + + ACE_OS::strncpy (s, this->devname_, len); + return 0; +} + +// Return a pointer to the address. + +ACE_INLINE void * +ACE_DEV_Addr::get_addr (void) const +{ + ACE_TRACE ("ACE_DEV_Addr::get_addr"); + + return (void *) &this->devname_; +} + +// Compare two addresses for equality. + +ACE_INLINE int +ACE_DEV_Addr::operator == (const ACE_Addr &sap) const +{ + ACE_TRACE ("ACE_DEV_Addr::operator="); + + return ACE_OS::strcmp (this->devname_, + ((ACE_DEV_Addr &) sap).devname_) == 0; +} + +// Compare two addresses for inequality. + +ACE_INLINE int +ACE_DEV_Addr::operator != (const ACE_Addr &sap) const +{ + ACE_TRACE ("ACE_DEV_Addr::operator!="); + + return !((*this) == sap); // This is lazy, of course... ;-). +} + +// Return the path name used for the rendezvous point. + +ACE_INLINE LPCTSTR +ACE_DEV_Addr::get_path_name (void) const +{ + ACE_TRACE ("ACE_DEV_Addr::get_path_name"); + + return this->devname_; +} + diff --git a/ace/DEV_Connector.cpp b/ace/DEV_Connector.cpp new file mode 100644 index 00000000000..967e7adb6f6 --- /dev/null +++ b/ace/DEV_Connector.cpp @@ -0,0 +1,40 @@ +// DEV_Connector.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/DEV_Connector.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_DEV_Connector) + +void +ACE_DEV_Connector::dump (void) const +{ + ACE_TRACE ("ACE_DEV_Connector::dump"); + + ACE_DEV::dump (); +} + +ACE_DEV_Connector::ACE_DEV_Connector (void) +{ + ACE_TRACE ("ACE_DEV_Connector::ACE_DEV_Connector"); +} + +int +ACE_DEV_Connector::connect (ACE_DEV_IO &new_io, + const ACE_DEV_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &, + int, + int flags, + int perms) +{ + ACE_TRACE ("ACE_DEV_Connector::connect"); + + ACE_HANDLE handle = ACE::handle_timed_open (timeout, + remote_sap.get_path_name (), + flags, perms); + new_io.set_handle (handle); + new_io.addr_ = remote_sap; // class copy. + return handle == ACE_INVALID_HANDLE ? -1 : 0; +} + diff --git a/ace/DEV_Connector.h b/ace/DEV_Connector.h new file mode 100644 index 00000000000..8a7e70941ff --- /dev/null +++ b/ace/DEV_Connector.h @@ -0,0 +1,86 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// DEV_Connector.h +// +// = AUTHOR +// Gerhard Lenzer and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_DEV_CONNECTOR_H) +#define ACE_DEV_CONNECTOR_H + +#include "ace/DEV_IO.h" + +class ACE_Export ACE_DEV_Connector : public ACE_DEV + // = TITLE + // Defines an active connection factory for the ACE_DEV wrappers. +{ +public: + ACE_DEV_Connector (void); + // Default constructor. + + ACE_DEV_Connector (ACE_DEV_IO &new_io, + const ACE_DEV_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + int connect (ACE_DEV_IO &new_io, + const ACE_DEV_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/DEV_Connector.i" + +#endif /* ACE_DEV_CONNECTOR_H */ diff --git a/ace/DEV_Connector.i b/ace/DEV_Connector.i new file mode 100644 index 00000000000..14e3f988137 --- /dev/null +++ b/ace/DEV_Connector.i @@ -0,0 +1,25 @@ +/* -*- C++ -*- */ +// $Id$ + +// DEV_Connector.i + +#include "ace/Log_Msg.h" + +// Creates a Local ACE_DEV. + +inline +ACE_DEV_Connector::ACE_DEV_Connector (ACE_DEV_IO &new_io, + const ACE_DEV_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_DEV_Connector::ACE_DEV_Connector"); + if (this->connect (new_io, remote_sap, timeout, local_sap, + reuse_addr, flags, perms) == ACE_IO_SAP::INVALID_HANDLE + && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + ACE_ERROR ((LM_ERROR, "address %s, %p\n", + remote_sap.get_path_name (), "ACE_DEV_IO")); +} diff --git a/ace/DEV_IO.cpp b/ace/DEV_IO.cpp new file mode 100644 index 00000000000..52b077a3ad3 --- /dev/null +++ b/ace/DEV_IO.cpp @@ -0,0 +1,97 @@ +// DEV_IO.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/DEV_IO.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_DEV_IO) + +void +ACE_DEV_IO::dump (void) const +{ + ACE_TRACE ("ACE_DEV_IO::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->addr_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Simple-minded do nothing constructor. + +ACE_DEV_IO::ACE_DEV_IO (void) +{ + ACE_TRACE ("ACE_DEV_IO::ACE_DEV_IO"); +} + +// Send N char *ptrs and int lengths. Note that the char *'s precede +// the ints (basically, an varargs version of writev). The count N is +// the *total* number of trailing arguments, *not* a couple of the +// number of tuple pairs! + +ssize_t +ACE_DEV_IO::send (size_t n, ...) const +{ + ACE_TRACE ("ACE_DEV_IO::send"); + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::writev (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + +// This is basically an interface to ACE_OS::readv, that doesn't use the +// struct iovec explicitly. The ... can be passed as an arbitrary +// number of (char *ptr, int len) tuples. However, the count N is the +// *total* number of trailing arguments, *not* a couple of the number +// of tuple pairs! + +ssize_t +ACE_DEV_IO::recv (size_t n, ...) const +{ + ACE_TRACE ("ACE_DEV_IO::recv"); + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::readv (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + diff --git a/ace/DEV_IO.h b/ace/DEV_IO.h new file mode 100644 index 00000000000..60368bf1d1e --- /dev/null +++ b/ace/DEV_IO.h @@ -0,0 +1,104 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// DEV_IO.h +// +// = AUTHOR +// Gerhard Lenzer and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_DEV_IO_H) +#define ACE_DEV_IO_H + +#include "ace/DEV.h" +#include "ace/DEV_Addr.h" + +class ACE_Export ACE_DEV_IO : public ACE_DEV + // = TITLE + // Read/Write operations on Devices. +{ +friend class ACE_DEV_Connector; +public: + ACE_DEV_IO (void); + // Default constructor. + + // = Various send operations. + ssize_t send (const void *buf, size_t n) const; + // send upto <n> bytes in <buf>. + + ssize_t recv (void *buf, size_t n) const; + // Recv upto <n> bytes in <buf>. + + ssize_t send_n (const void *buf, size_t n) const; + // Send n bytes, keep trying until n are sent. + + ssize_t recv_n (void *buf, size_t n) const; + // Recv n bytes, keep trying until n are received. + +#if defined (ACE_HAS_STREAM_PIPES) + ssize_t recv (ACE_Str_Buf *cntl, + ACE_Str_Buf *data, + int *band, + int *flags) const; + // Recv bytes via STREAM pipes using "band" mode. + + ssize_t send (const ACE_Str_Buf *cntl, + const ACE_Str_Buf *data, + int band, + int flags = 0) const; + // Send bytes via STREAM pipes using "band" mode. + + ssize_t recv (ACE_Str_Buf *cntl, + ACE_Str_Buf *data, + int *flags) const; + // Recv <cntl> and <data> via STREAM pipes. + + ssize_t send (const ACE_Str_Buf *cntl, + const ACE_Str_Buf *data, + int flags = 0) const; + // Send <cntl> and <data> via STREAM pipes. +#endif /* ACE_HAS_STREAM_PIPES */ + + ssize_t send (const iovec iov[], size_t n) const; + // Send iovecs via <::writev>. + + ssize_t recv (iovec iov[], size_t n) const; + // Recv iovecs via <::readv>. + + ssize_t send (size_t n, ...) const; + // Send N char *ptrs and int lengths. Note that the char *'s + // precede the ints (basically, an varargs version of writev). The + // count N is the *total* number of trailing arguments, *not* a + // couple of the number of tuple pairs! + + ssize_t recv (size_t n, ...) const; + // This is an interface to ::readv, that doesn't use the struct + // iovec explicitly. The ... can be passed as an arbitrary number + // of (char *ptr, int len) tuples. However, the count N is the + // *total* number of trailing arguments, *not* a couple of the + // number of tuple pairs! + + ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Send <n> bytes via Win32 WriteFile using overlapped I/O. + + ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Recv <n> bytes via Win32 ReadFile using overlapped I/O. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/DEV_IO.i" + +#endif /* ACE_DEV_IO_H */ diff --git a/ace/DEV_IO.i b/ace/DEV_IO.i new file mode 100644 index 00000000000..0597aa44b55 --- /dev/null +++ b/ace/DEV_IO.i @@ -0,0 +1,102 @@ +/* -*- C++ -*- */ +// $Id$ + +// DEV_IO.i + + +// Send exactly N bytes from BUF to this device. Keeping trying until +// this many bytes are sent. + +inline ssize_t +ACE_DEV_IO::send_n (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_DEV_IO::send_n"); + return ACE::write_n (this->get_handle (), buf, n); +} + +// Receive exactly N bytes from this file into BUF. Keep trying until +// this many bytes are received. + +inline ssize_t +ACE_DEV_IO::recv_n (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_DEV_IO::recv_n"); + return ACE::read_n (this->get_handle (), buf, n); +} + +inline ssize_t +ACE_DEV_IO::send (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_DEV_IO::send"); + return ACE_OS::write (this->get_handle (), (const char *) buf, n); +} + +inline ssize_t +ACE_DEV_IO::recv (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_DEV_IO::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n); +} + +inline ssize_t +ACE_DEV_IO::send (const iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_DEV_IO::send"); + return ACE_OS::writev (this->get_handle (), (iovec *) iov, n); +} + +inline ssize_t +ACE_DEV_IO::recv (iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_DEV_IO::recv"); + return ACE_OS::readv (this->get_handle (), (iovec *) iov, n); +} + +inline ssize_t +ACE_DEV_IO::send (const void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_DEV_IO::send"); + return ACE_OS::write (this->get_handle (), + (const char *) buf, n, + overlapped); +} + +inline ssize_t +ACE_DEV_IO::recv (void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_DEV_IO::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n, + overlapped); +} + +#if defined (ACE_HAS_STREAM_PIPES) +inline ssize_t +ACE_DEV_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *band, int *flags) const +{ + ACE_TRACE ("ACE_DEV_IO::recv"); + return ACE_OS::getpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags); +} + +inline ssize_t +ACE_DEV_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int band, int flags) const +{ + ACE_TRACE ("ACE_DEV_IO::send"); + return ACE_OS::putpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags); +} + +inline ssize_t +ACE_DEV_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *flags) const +{ + ACE_TRACE ("ACE_DEV_IO::recv"); + return ACE_OS::getmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags); +} + +inline ssize_t +ACE_DEV_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int flags) const +{ + ACE_TRACE ("ACE_DEV_IO::send"); + return ACE_OS::putmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags); +} +#endif /* ACE_HAS_STREAM_PIPES */ diff --git a/ace/Date_Time.cpp b/ace/Date_Time.cpp new file mode 100644 index 00000000000..0aeb72780f0 --- /dev/null +++ b/ace/Date_Time.cpp @@ -0,0 +1,5 @@ +// Date_Time.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Date_Time.h" diff --git a/ace/Date_Time.h b/ace/Date_Time.h new file mode 100644 index 00000000000..7f7dcbd33ad --- /dev/null +++ b/ace/Date_Time.h @@ -0,0 +1,92 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE_Date_Time.h +// +// = AUTHOR +// Tim Harrison (harrison@cs.wustl.edu) (and he's darn proud of this ;-)) +// +// ============================================================================ + +#if !defined (ACE_DATE_TIME_H) +#define ACE_DATE_TIME_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Date_Time + // = TITLE + // System independent representation of date and time. +{ +public: + // constructor with init values, no check for validy + ACE_Date_Time (long day = 0, + long month = 0, + long year = 0, + long hour = 0, + long minute = 0, + long second = 0, + long microsec = 0); + // Set/get portions of ACE_Date_Time, no check for validity. + + long day (void); + // Get day. + + void day (long day); + // Set day. + + long month (void); + // Get month. + + void month (long month); + // Set month. + + long year (void); + // Get year. + + void year (long year); + // Set year. + + long hour (void); + // Get hour. + + void hour (long hour); + // Set hour. + + long minute (void); + // Get minute. + + void minute (long minute); + // Set minute. + + long second (void); + // Get second. + + void second (long second); + // Set second. + + long microsec (void); + // Get microsec. + + void microsec (long microsec); + // Set microsec. + +private: + long day_; + long month_; + long year_; + long hour_; + long minute_; + long second_; + long microsec_; +}; + +#include "ace/Date_Time.i" + +#endif /* ACE_DATE_TIME_H */ diff --git a/ace/Date_Time.i b/ace/Date_Time.i new file mode 100644 index 00000000000..829e91c003f --- /dev/null +++ b/ace/Date_Time.i @@ -0,0 +1,140 @@ +/* -*- C++ -*- */ +// $Id$ + +// Date_Time.i + +// constructor with init values, no check for validy +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 +inline long +ACE_Date_Time::day (void) +{ + ACE_TRACE ("ACE_Date_Time::day"); + return day_; +} + +// set day +inline void +ACE_Date_Time::day (long day) +{ + ACE_TRACE ("ACE_Date_Time::day"); + day_ = day; +} + +// get month +inline long +ACE_Date_Time::month (void) +{ + ACE_TRACE ("ACE_Date_Time::month"); + return month_; +} + +// set month +inline void +ACE_Date_Time::month (long month) +{ + ACE_TRACE ("ACE_Date_Time::month"); + month_ = month; +} + +// get year +inline long +ACE_Date_Time::year (void) +{ + ACE_TRACE ("ACE_Date_Time::year"); + return year_; +} + +// set year +inline void +ACE_Date_Time::year (long year) +{ + ACE_TRACE ("ACE_Date_Time::year"); + year_ = year; +} + +// get hour +inline long +ACE_Date_Time::hour (void) +{ + ACE_TRACE ("ACE_Date_Time::hour"); + return hour_; +} + +// set hour +inline void +ACE_Date_Time::hour (long hour) +{ + ACE_TRACE ("ACE_Date_Time::hour"); + hour_ = hour; +} + +// get minute +inline long +ACE_Date_Time::minute (void) +{ + ACE_TRACE ("ACE_Date_Time::minute"); + return minute_; +} + +// set minute +inline void +ACE_Date_Time::minute (long minute) +{ + ACE_TRACE ("ACE_Date_Time::minute"); + minute_ = minute; +} + +// get second +inline long +ACE_Date_Time::second (void) +{ + ACE_TRACE ("ACE_Date_Time::second"); + return second_; +} + +// set second +inline void +ACE_Date_Time::second (long second) +{ + ACE_TRACE ("ACE_Date_Time::second"); + second_ = second; +} + +// get microsec +inline long +ACE_Date_Time::microsec (void) +{ + ACE_TRACE ("ACE_Date_Time::microsec"); + return microsec_; +} + +// set microsec +inline void +ACE_Date_Time::microsec (long microsec) +{ + ACE_TRACE ("ACE_Date_Time::microsec"); + microsec_ = microsec; +} + + diff --git a/ace/Dump.cpp b/ace/Dump.cpp new file mode 100644 index 00000000000..ea231f6b243 --- /dev/null +++ b/ace/Dump.cpp @@ -0,0 +1,132 @@ +// Dump.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Dump.h" + +#if defined (ACE_MT_SAFE) +// Synchronize output operations. +ACE_Thread_Mutex ACE_ODB::ace_dump_lock_; +#endif /* ACE_MT_SAFE */ + +// Implementations (very simple for now...) + +ACE_Dumpable::~ACE_Dumpable (void) +{ + ACE_TRACE ("ACE_Dumpable::~ACE_Dumpable"); +} + +ACE_Dumpable::ACE_Dumpable (const void *this_ptr) + : this_ (this_ptr) +{ + ACE_TRACE ("ACE_Dumpable::ACE_Dumpable"); +} + +ACE_Dumpable_Ptr::ACE_Dumpable_Ptr (const ACE_Dumpable *dumper) + : dumper_ (dumper) +{ + ACE_TRACE ("ACE_Dumpable_Ptr::ACE_Dumpable_Ptr"); +} + +const ACE_Dumpable * +ACE_Dumpable_Ptr::operator->() const +{ + ACE_TRACE ("ACE_Dumpable_Ptr::operator->"); + return this->dumper_; +} + +void +ACE_Dumpable_Ptr::operator= (const ACE_Dumpable *dumper) const +{ + ACE_TRACE ("ACE_Dumpable_Ptr::operator="); + if (this->dumper_ != dumper) + { + delete (ACE_Dumpable_Ptr *) this->dumper_; + ((ACE_Dumpable_Ptr *) this)->dumper_ = dumper; + } +} + +ACE_ODB::ACE_ODB (void) +{ + ACE_TRACE ("ACE_ODB::ACE_ODB"); +} + +ACE_ODB * +ACE_ODB::instance (void) +{ + ACE_TRACE ("ACE_ODB::instance"); + + if (ACE_ODB::instance_ == 0) + { + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_ODB::ace_dump_lock_, 0)); + + if (ACE_ODB::instance_ == 0) + ACE_NEW_RETURN (ACE_ODB::instance_, ACE_ODB, 0); + } + + return ACE_ODB::instance_; +} + +void +ACE_ODB::dump_objects (void) +{ + ACE_TRACE ("ACE_ODB::dump_objects"); + for (int i = 0; i < this->current_size_; i++) + { + if (this->object_table_[i].this_ != 0) + // Dump the state of the object. + this->object_table_[i].dumper_->dump (); + } +} + +// This method registers a new <dumper>. It detects +// duplicates and simply overwrites them. + +void +ACE_ODB::register_object (const ACE_Dumpable *dumper) +{ + ACE_TRACE ("ACE_ODB::register_object"); + int i; + int slot; + + for (i = 0; i < this->current_size_; i++) + { + if (this->object_table_[i].this_ == 0) + slot = i; + else if (this->object_table_[i].this_ == dumper->this_) + { + slot = i; + break; + } + } + + if (i == this->current_size_) + { + slot = this->current_size_++; + ACE_ASSERT (this->current_size_ < ACE_ODB::MAX_TABLE_SIZE); + } + this->object_table_[slot].this_ = dumper->this_; + this->object_table_[slot].dumper_ = dumper; +} + +void +ACE_ODB::remove_object (const void *this_ptr) +{ + ACE_TRACE ("ACE_ODB::remove_object"); + int i; + + for (i = 0; i < this->current_size_; i++) + { + if (this->object_table_[i].this_ == this_ptr) + break; + } + + if (i < this->current_size_) + { + this->object_table_[i].this_ = 0; + this->object_table_[i].dumper_ = 0; + } +} + +ACE_ODB *ACE_ODB::instance_ = 0; + diff --git a/ace/Dump.h b/ace/Dump.h new file mode 100644 index 00000000000..51e8e0d5a9b --- /dev/null +++ b/ace/Dump.h @@ -0,0 +1,166 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Dump.h +// +// = DESCRIPTION +// +// A prototype mechanism that allow all ACE objects to be registered +// with a central in-memory "database" that can dump the state of all +// live ACE objects (e.g., from within a debugger). +// +// To turn on this feature simply compile with -DACE_NDEBUG +// +// There are several interesting aspects to this design: +// +// 1. It uses the External Polymorphism pattern to avoid having to +// derive all ACE classes from a common base class that has virtual +// methods (this is crucial to avoid unnecessary overhead). In +// addition, there is no additional space added to ACE objects +// (this is crucial to maintain binary layout compatibility). +// +// 2. This mechanism can be conditionally compiled in order to +// completely disable this feature entirely. Moreover, by +// using macros there are relatively few changes to ACE code. +// +// 3. This mechanism copes with single-inheritance hierarchies of +// dumpable classes. In such cases we typically want only one +// dump, corresponding to the most derived instance. Thanks to +// Christian Millour (chris@etca.fr) for illustrating how to do +// this. Note, however, that this scheme doesn't generalize to +// work with multiple-inheritance or virtual base classes. +// +// Future work includes: +// +// 1. Using a dynamic object table rather than a static table +// +// 2. Adding support to allow particular classes of objects to +// be selectively dumped. +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_DUMP_H) +#define ACE_DUMP_H + +#include "ace/Synch.h" + +class ACE_Export ACE_Dumpable + // = TITLE + // Base class that defines a uniform interface for all object + // dumping. +{ +friend class ACE_ODB; +friend class ACE_Dumpable_Ptr; +public: + ACE_Dumpable (const void *); + + virtual void dump (void) const = 0; + // This pure virtual method must be filled in by a subclass. + +protected: + virtual ~ACE_Dumpable (void); + +private: + const void *this_; + // Pointer to the object that is being stored. +}; + +class ACE_Export ACE_Dumpable_Ptr + // = TITLE + // A smart pointer stored in the in-memory object database + // ACE_ODB. The pointee (if any) is deleted when reassigned. +{ +public: + ACE_Dumpable_Ptr (const ACE_Dumpable *dumper = 0); + const ACE_Dumpable *operator->() const; + void operator= (const ACE_Dumpable *dumper) const; + +private: + const ACE_Dumpable *dumper_; + // "Real" pointer to the underlying abstract base class + // pointer that does the real work. +}; + +class ACE_Export ACE_ODB + // = TITLE + // This is the object database (ODB) that keeps track of all + // live ACE objects. +{ +public: + enum {MAX_TABLE_SIZE = 100000}; // This is clearly inadequate and should be dynamic... + + void dump_objects (void); + // Iterates through the entire set of registered objects and + // dumps their state. + + void register_object (const ACE_Dumpable *dumper); + // Add the tuple <dumper, this_> to the list of registered ACE objects. + + void remove_object (const void *this_); + // Use <this_> to locate and remove the associated <dumper> from the + // list of registered ACE objects. + + static ACE_ODB *instance (void); + // Interface to the Singleton instance of the object database. + +private: + ACE_ODB (void); // Ensure we have a Singleton... + + struct Tuple + { + const void *this_; + // Pointer to the object that is registered. + + const ACE_Dumpable_Ptr dumper_; + // Smart pointer to the ACE_Dumpable object associated with this_. + // This uses an ACE_Dumpable_Ptr, instead of a bare pointer, to + // cope with hierarchies of dumpable classes. In such cases we + // typically want only one dump, corresponding to the most derived + // instance. To achieve this, the handle registered for the + // subobject corresponding to the base class is destroyed (hence + // on destruction of the subobject its handle won't exist anymore + // and we'll have to check for that). + Tuple() : dumper_(0) {} + }; + + static ACE_ODB *instance_; + // Singleton instance of this class. + + Tuple object_table_[ACE_ODB::MAX_TABLE_SIZE]; + // The current implementation is very simple-minded and will be + // changed to be dynamic. + + int current_size_; + // Current size of <object_table_>. + +#if defined (ACE_MT_SAFE) + static ACE_Thread_Mutex ace_dump_lock_; + // Double-Check lock. +#endif /* ACE_MT_SAFE */ +}; + +#include "ace/Dump_T.h" + +// Some useful macros for conditionally compiling this feature... +#if defined (ACE_NDEBUG) +#define ACE_REGISTER_OBJECT(CLASS) +#define ACE_REMOVE_OBJECT +#else +#define ACE_REGISTER_OBJECT(CLASS) \ + ACE_ODB::instance ()->register_object \ + (new ACE_Dumpable_Adapter<CLASS> (this)); +#define ACE_REMOVE_OBJECT \ + ACE_ODB::instance ()->remove_object \ + ((void *) this); +#endif /* ACE_NDEBUG */ +#endif /* ACE_DUMP_H */ diff --git a/ace/Dump_T.cpp b/ace/Dump_T.cpp new file mode 100644 index 00000000000..71c2cbeed30 --- /dev/null +++ b/ace/Dump_T.cpp @@ -0,0 +1,35 @@ +// Dump_T.cpp +// $Id$ + +#if !defined (ACE_DUMP_T_C) +#define ACE_DUMP_T_C + +#include "ace/Dump_T.h" + +template <class Concrete> +ACE_Dumpable_Adapter<Concrete>::~ACE_Dumpable_Adapter (void) +{ + ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::~ACE_Dumpable_Adapter"); +} + +template <class Concrete> +ACE_Dumpable_Adapter<Concrete>::ACE_Dumpable_Adapter (const Concrete *t) + : this_ (t), ACE_Dumpable ((const void *) t) +{ + ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::ACE_Dumpable_Adapter"); +} + +template <class Concrete> Concrete * +ACE_Dumpable_Adapter<Concrete>::operator->() const +{ + return (Concrete *) this->this_; +} + +template <class Concrete> void +ACE_Dumpable_Adapter<Concrete>::dump (void) const +{ + ACE_TRACE ("ACE_Dumpable_Adapter<Concrete>::dump"); + this->this_->dump (); +} + +#endif /* ACE_DUMP_T_C */ diff --git a/ace/Dump_T.h b/ace/Dump_T.h new file mode 100644 index 00000000000..f1031796341 --- /dev/null +++ b/ace/Dump_T.h @@ -0,0 +1,61 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Dump.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_DUMP_T_H) +#define ACE_DUMP_T_H + +#include "ace/Dump.h" + +template <class Concrete> +class ACE_Dumpable_Adapter : public ACE_Dumpable + // = TITLE + // This class inherits the interface of the abstract ACE_Dumpable + // class and is instantiated with the implementation of the + // concrete component class <class Concrete>. + // + // = DESCRIPTION + // This design is similar to the Adapter and Decorator patterns + // from the ``Gang of Four'' book. Note that <class Concrete> + // need not inherit from a common class since ACE_Dumpable + // provides the uniform virtual interface! +{ +public: + // = Initialization and termination methods. + ACE_Dumpable_Adapter (const Concrete *t); + ~ACE_Dumpable_Adapter (void); + + virtual void dump (void) const; + // Concrete dump method (simply delegates to the <dump> method of + // <class Concrete>). + + Concrete *operator->() const; + // Delegate to methods in the Concrete class. + +private: + const Concrete *this_; + // Pointer to <this> of <class Concrete>. +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Dump_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Dump_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_DUMP_T_H */ diff --git a/ace/Dynamic.cpp b/ace/Dynamic.cpp new file mode 100644 index 00000000000..a94654b56a8 --- /dev/null +++ b/ace/Dynamic.cpp @@ -0,0 +1,16 @@ +// Dynamic.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Dynamic.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Dynamic.i" +#endif /* __ACE_INLINE__ */ + +ACE_Dynamic::ACE_Dynamic (void) + : instance_ (0) +{ + ACE_TRACE ("ACE_Dynamic::ACE_Dynamic"); +} + diff --git a/ace/Dynamic.h b/ace/Dynamic.h new file mode 100644 index 00000000000..569f029b6c6 --- /dev/null +++ b/ace/Dynamic.h @@ -0,0 +1,52 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE_Dynamic.h +// +// = AUTHOR +// Doug Schmidt and Irfan Pyrarli. +// +// ============================================================================ + +#if !defined (ACE_DYNAMIC_H) +#define ACE_DYNAMIC_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Dynamic + // = TITLE + // Checks to see if a Svc_Handler was dynamically allocated. + // + // = DESCRIPTION + // This class holds the pointer in a thread-safe manner between + // the call to operator new and the call to the constructor. +{ +public: + ACE_Dynamic (void); + + void *set (void *x); + // Assign the new pointer to <instance_> in order to keep it safe + // until we can compare it in the constructor. + + int is_dynamic (void *x); + // 1 if we were allocated dynamically, else 0. + +private: + void *instance_; + // Holds the pointer in a thread-safe manner between the call to + // operator new and the call to the constructor. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Dynamic.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_DYNAMIC_H */ + diff --git a/ace/Dynamic.i b/ace/Dynamic.i new file mode 100644 index 00000000000..9f051363c30 --- /dev/null +++ b/ace/Dynamic.i @@ -0,0 +1,18 @@ +/* -*- C++ -*- */ +// $Id$ + +// Dynamic.i + +ACE_INLINE void * +ACE_Dynamic::set (void *x) +{ + ACE_TRACE ("ACE_Dynamic::set"); + return this->instance_ = x; +} + +ACE_INLINE int +ACE_Dynamic::is_dynamic (void *x) +{ + ACE_TRACE ("ACE_Dynamic::is_dynamic"); + return this->instance_ == x; +} diff --git a/ace/Dynamic_Service.cpp b/ace/Dynamic_Service.cpp new file mode 100644 index 00000000000..05fec7a0913 --- /dev/null +++ b/ace/Dynamic_Service.cpp @@ -0,0 +1,46 @@ +// Dynamic_Service.cpp +// $Id$ + +#if !defined (ACE_DYNAMIC_SERVICE_C) +#define ACE_DYNAMIC_SERVICE_C + +#define ACE_BUILD_DLL +#include "ace/Service_Config.h" +#include "ace/Service_Repository.h" +#include "ace/Dynamic_Service.h" + +template <class SERVICE> void +ACE_Dynamic_Service<SERVICE>::dump (void) const +{ + ACE_TRACE ("ACE_Dynamic_Service<SERVICE>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Get the instance using <name>. + +template <class SERVICE> SERVICE * +ACE_Dynamic_Service<SERVICE>::instance (const char *name) +{ + ACE_TRACE ("ACE_Dynamic_Service::instance"); + const ACE_Service_Record *svc_rec; + + if (ACE_Service_Config::svc_rep ()->find (name, &svc_rec) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "svc_rep"), 0); + + const ACE_Service_Type *type = svc_rec->type (); + + if (type == 0) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "type"), 0); + else + { + const void *obj = type->object (); + // This should be an RTTI typesafe downcast... + SERVICE *n = (SERVICE *) obj; + return n; + } +} + +#endif /* ACE_DYNAMIC_SERVICE_C */ diff --git a/ace/Dynamic_Service.h b/ace/Dynamic_Service.h new file mode 100644 index 00000000000..35ac1d94c25 --- /dev/null +++ b/ace/Dynamic_Service.h @@ -0,0 +1,47 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Dynamic_Service.h +// +// = AUTHOR +// Prashant Jain, Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_DYNAMIC_SERVICE_H) +#define ACE_DYNAMIC_SERVICE_H + +template <class SERVICE> +class ACE_Dynamic_Service + // = TITLE + // Provides a general interface to retrieve arbitrary objects + // from the ACE service repository. + // + // = DESCRIPTION + // Uses "name" for lookup in the ACE service repository. Obtains + // the object and returns it as the appropriate type. +{ +public: + static SERVICE *instance (const char *name); + // Return instance using <name> to search the Service_Repository. + + void dump (void) const; + // Dump the current state of the object. +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Dynamic_Service.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Dynamic_Service.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_DYNAMIC_SERVICE_H */ diff --git a/ace/Dynamic_Service.i b/ace/Dynamic_Service.i new file mode 100644 index 00000000000..a29b996d459 --- /dev/null +++ b/ace/Dynamic_Service.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Dynamic_Service.i diff --git a/ace/Event_Handler.cpp b/ace/Event_Handler.cpp new file mode 100644 index 00000000000..c0cc76fbd09 --- /dev/null +++ b/ace/Event_Handler.cpp @@ -0,0 +1,11 @@ +// Event_Handler.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Event_Handler.h" +#include "ace/Message_Block.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Event_Handler.i" +#endif /* __ACE_INLINE__ */ + diff --git a/ace/Event_Handler.h b/ace/Event_Handler.h new file mode 100644 index 00000000000..bbe19e5b7fa --- /dev/null +++ b/ace/Event_Handler.h @@ -0,0 +1,150 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Event_Handler.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_EVENT_HANDLER_H) +#define ACE_EVENT_HANDLER_H + +#include "ace/ACE.h" + +// Forward declaration. +class ACE_Message_Block; + +typedef u_long ACE_Reactor_Mask; + +class ACE_Export ACE_Event_Handler + // = TITLE + // Provides an abstract interface for handling various types of + // I/O, timer, and signal events. + // + // = DESCRIPTION + // Derived classes read/write input/output on an I/O + // descriptor, handle an exception raised on an I/O + // descriptor, handle a timer's expiration, or handle a + // signal. +{ +public: + enum + { + LO_PRIORITY = 0, + HI_PRIORITY = 10, + NULL_MASK = 0, +#if defined (ACE_USE_POLL) + READ_MASK = POLLIN, + WRITE_MASK = POLLOUT, + EXCEPT_MASK = POLLPRI, +#else /* USE SELECT */ + READ_MASK = 0x1, + WRITE_MASK = 0x4, + EXCEPT_MASK = 0x2, +#endif /* ACE_USE_POLL */ + RWE_MASK = READ_MASK | WRITE_MASK | EXCEPT_MASK, + DONT_CALL = 0x100 + }; + + virtual ~ACE_Event_Handler (void); + // Destructor is virtual to enable proper cleanup. + + // = The following methods must be supplied by subclasses in order + // to specialize the behavior of an Event_Handler. + virtual ACE_HANDLE get_handle (void) const; + // Get the I/O handle. + virtual void set_handle (ACE_HANDLE); + // Set the I/O handle. + + // = Priority runs from MIN_PRIORITY (which is the "lowest + // priority") to MAX_PRIORITY (which is the "highest priority"). + virtual int get_priority (void) const; + // Get the priority of the Event_Handler. + virtual void set_priority (int priority); + // Set the priority of the Event_Handler. + + virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE); + // Called when input events occur (e.g., connection or data). + + virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE); + // Called when output events are possible (e.g., flow control + // abates). + + virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE); + // Called when execption events occur (e.g., SIGURG). + + virtual int handle_timeout (const ACE_Time_Value &tv, + const void *arg = 0); + // Called when timer expires. + + virtual int handle_close (ACE_HANDLE fd, + ACE_Reactor_Mask close_mask); + // Called when object is removed from the ACE_Reactor + + virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0); + // Called when object is signaled by OS (either via UNIX signals or + // when a Win32 object becomes signaled). + + // = Proactor callbacks. + // Win32 specific. An Event_Handler can be given to a Proactor + // with a {RECV,SEND}_MASK. The Proactor calls back + // <get_message> and <get_handle> to perform the correct + // operations (send/recv). When the send/recv is complete, + // handle_{input,output} is called. Thus, Event_Handlers are + // used for "proactive I/O" where they are told WHEN THE + // OPERATION IS COMPLETE. Alternatively, the _Reactor_ tells + // Event_Handlers WHEN THE OPERATION CAN BE PERFORMED. + + virtual int handle_input_complete (ACE_Message_Block *message, + long bytes_transferred); + // Called back by the Proactor when an asynchronous input operation + // is complete. If this method returns > 0 the Proactor will + // initiate another asynchronous receive; if a 0 is returned the + // Proactor will not reinitiate a receive; and if a -1 is returned, + // then no receive is reinitiated and <handle_close> is called. If + // <bytes_transferred> >= 0, then the I/O operation completed + // successfully. If <bytes_transferred> == -1, then the I/O + // operation failed. Check <message> for total bytes received and + // errno for reason. + + virtual int handle_output_complete (ACE_Message_Block *message, + long bytes_transferred); + // Called back by the Proactor when an asynchronous output operation + // is complete. If this method returns > 0 the Proactor will + // initiate another asynchronous send; if a 0 is returned the + // Proactor will not reinitiate a send; and if a -1 is returned, + // then no send is reinitiated and <handle_close> is called. If + // <bytes_transferred> >= 0, then the I/O operation completed + // successfully. If <bytes_transferred> == -1, then the I/O + // operation failed. Check <message> for total bytes received and + // errno for reason. + + virtual ACE_Message_Block *get_message (void); + // Factory that creates an <ACE_Message_Block> that is used by the + // Proactor to send or receive a message asynchronously. When the + // asynchronous call completes, this message is returned to the + // <IO_Handler> with its contents filled in. By default, + // get_message dynamically creates a new ACE_Message_Block. + +protected: + ACE_Event_Handler (void); + // Force ACE_Event_Handler to be an abstract base class. + + int priority_; + // Priority of this Event_Handler. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Event_Handler.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_EVENT_HANDLER_H */ diff --git a/ace/Event_Handler.i b/ace/Event_Handler.i new file mode 100644 index 00000000000..a1211800662 --- /dev/null +++ b/ace/Event_Handler.i @@ -0,0 +1,135 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "ace/Event_Handler.h" +// Event_Handler.i + +// Implement conceptually abstract virtual functions in the base class +// so derived classes don't have to implement unused ones. + +ACE_INLINE +ACE_Event_Handler::ACE_Event_Handler (void) + : priority_ (ACE_Event_Handler::LO_PRIORITY) +{ + ACE_TRACE ("ACE_Event_Handler::ACE_Event_Handler"); +} + +ACE_INLINE +ACE_Event_Handler::~ACE_Event_Handler (void) +{ + ACE_TRACE ("ACE_Event_Handler::~ACE_Event_Handler"); +} + +// Gets the file descriptor associated with this I/O device. + +ACE_INLINE ACE_HANDLE +ACE_Event_Handler::get_handle (void) const +{ + ACE_TRACE ("ACE_Event_Handler::get_handle"); + return ACE_INVALID_HANDLE; +} + +// Sets the file descriptor associated with this I/O device. + +ACE_INLINE void +ACE_Event_Handler::set_handle (ACE_HANDLE) +{ + ACE_TRACE ("ACE_Event_Handler::set_handle"); +} + +// Gets the priority of this handler. + +ACE_INLINE int +ACE_Event_Handler::get_priority (void) const +{ + ACE_TRACE ("ACE_Event_Handler::get_priority"); + return this->priority_; +} + +// Sets the priority + +ACE_INLINE void +ACE_Event_Handler::set_priority (int priority) +{ + ACE_TRACE ("ACE_Event_Handler::set_priority"); + this->priority_ = priority; +} + +// Called when the object is about to be removed from the Dispatcher +// tables. + +ACE_INLINE int +ACE_Event_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask) +{ + ACE_TRACE ("ACE_Event_Handler::handle_close"); + return -1; +} + +// Called when input becomes available on fd. + +ACE_INLINE int +ACE_Event_Handler::handle_input (ACE_HANDLE) +{ + ACE_TRACE ("ACE_Event_Handler::handle_input"); + return -1; +} + +// Called when output is possible on fd. + +ACE_INLINE int +ACE_Event_Handler::handle_output (ACE_HANDLE) +{ + ACE_TRACE ("ACE_Event_Handler::handle_output"); + return -1; +} + +// Called when urgent data is available on fd. + +ACE_INLINE int +ACE_Event_Handler::handle_exception (ACE_HANDLE) +{ + ACE_TRACE ("ACE_Event_Handler::handle_exception"); + return -1; +} + +// Called when timer expires, TV stores the current time. + +ACE_INLINE int +ACE_Event_Handler::handle_timeout (const ACE_Time_Value &, const void *) +{ + ACE_TRACE ("ACE_Event_Handler::handle_timeout"); + return -1; +} + +// Called when a registered signal occurs. + +ACE_INLINE int +ACE_Event_Handler::handle_signal (int, siginfo_t *, ucontext_t *) +{ + ACE_TRACE ("ACE_Event_Handler::handle_signal"); + return -1; +} + +ACE_INLINE int +ACE_Event_Handler::handle_input_complete (ACE_Message_Block *message, + long bytes_transfered) +{ + ACE_TRACE ("ACE_Event_Handler::handle_input_complete"); + return -1; +} + +ACE_INLINE int +ACE_Event_Handler::handle_output_complete (ACE_Message_Block *message, + long bytes_transfered) +{ + ACE_TRACE ("ACE_Event_Handler::handle_input_complete"); + return -1; +} + +ACE_INLINE ACE_Message_Block * +ACE_Event_Handler::get_message (void) +{ + ACE_TRACE ("ACE_Event_Handler::get_message"); + return 0; +} + diff --git a/ace/Event_Handler_T.cpp b/ace/Event_Handler_T.cpp new file mode 100644 index 00000000000..dcc36466413 --- /dev/null +++ b/ace/Event_Handler_T.cpp @@ -0,0 +1,54 @@ +// Event_Handler_T.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Event_Handler_T.h" + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) + +#if !defined (__ACE_INLINE__) +#include "ace/Event_Handler_T.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Event_Handler_T) + +template <class T> void +ACE_Event_Handler_T<T>::dump (void) const +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::dump"); +} + +template<class T> +ACE_Event_Handler_T<T>::~ACE_Event_Handler_T (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::~ACE_Event_Handler_T"); + if (this->delete_handler_) + delete this->op_handler_; +} + +template <class T> +ACE_Event_Handler_T<T>::ACE_Event_Handler_T (T *op_handler, int delete_handler, + GET_HANDLE get_handle, + IO_HANDLER input_h, + CL_HANDLER close_h, + SIG_HANDLER sig_h, + TO_HANDLER timeout_h, + IO_HANDLER output_h, + SET_HANDLE set_handle, + IO_HANDLER except_h) + : op_handler_ (op_handler), + delete_handler_ (delete_handler), + get_handle_ (get_handle), + input_handler_ (input_h), + cl_handler_ (close_h), + sig_handler_ (sig_h), + to_handler_ (timeout_h), + output_handler_ (output_h), + set_handle_ (set_handle), + except_handler_ (except_h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::ACE_Event_Handler_T"); +} + +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + diff --git a/ace/Event_Handler_T.h b/ace/Event_Handler_T.h new file mode 100644 index 00000000000..c78ace07609 --- /dev/null +++ b/ace/Event_Handler_T.h @@ -0,0 +1,180 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Event_Handler_T.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_EVENT_HANDLER_T_H) +#define ACE_EVENT_HANDLER_T_H + +#include "ace/Event_Handler.h" + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) + +template <class T> +class ACE_Export ACE_Event_Handler_T : public ACE_Event_Handler + // = TITLE + // Enable a class that doesn't inherit from the + // ACE_Event_Handler to be incorporated into the ACE_Reactor + // framework. Thanks to Greg Lavender (g.lavender@isode.com) + // for sharing this idea. + // + // = DESCRIPTION + // It is sometimes the case that an application has a hierarchy + // of operation dispatcher classes that have their own inheritance + // hierarchy but also would like to integrate with the ACE_Reactor. + // Rather than adopt a "mixin" approach, it is often cleaner to + // define a template as a subclass of ACE_Event_Handler and paramterize it + // with an operation dispatcher type. + // + // When constructing an instantiation of the ACE_Event_Handler_T object, + // a set of pointers to member functions must be provided so that + // when one of the handle_* methods is called by the ACE_Reactor, + // the appropriate method is called on the underlying operations + // object. This is done since in some cases it is useful to + // map any event that happens to the same method on an object. + // + // The ACE_Event_Handler_T template is instantiated by an operations + // object and registered with the ACE_Reactor, and it then calls the + // appropriate op_handler. So, it's basically just another + // level of indirection in event dispatching. The coupling + // betweent the ultimate handler of the event and the + // ACE_Event_Handler class is relaxed a bit by have this + // intermediate <op_handler_> object of type <T> around. The client + // object can then dynamically change the bindings for the + // various handlers so that during the life of one of the + // operation objects, it can change how it wants events to be + // handled. It just instantiates a new instance of the template + // with different bindings and reregisters this new object with + // the ACE_Reactor. +{ +public: + // = Typedefs to simplify pointer-to-member-function registration. + + // Get/set the underlying handle. + typedef ACE_HANDLE (T::*GET_HANDLE) (void) const; + typedef void (T::*SET_HANDLE) (ACE_HANDLE); + + typedef int (T::*IO_HANDLER) (ACE_HANDLE); + // Handle I/O events. + + typedef int (T::*TO_HANDLER) (const ACE_Time_Value &, const void *); + // Handle timeout events. + + typedef int (T::*CL_HANDLER) (ACE_HANDLE, ACE_Reactor_Mask); + // Handle close events. + + typedef int (T::*SIG_HANDLER) (ACE_HANDLE +#if defined(ACE_HAS_SIGINFO_T) +, siginfo_t*, ucontext_t* +#endif /* ACE_HAS_SIGINFO_T */ +); + // = Initialization and termination methods. + + ACE_Event_Handler_T (T *op_handler, + int delete_handler, + GET_HANDLE get_handle = 0, + IO_HANDLER input = 0, + CL_HANDLER close = 0, + SIG_HANDLER sig = 0, + TO_HANDLER timeout = 0, + IO_HANDLER output = 0, + SET_HANDLE set_handle = 0, + IO_HANDLER except = 0); + // Initialize the op_handler. + + ~ACE_Event_Handler_T (void); + // Close down and delete the <op_handler> + + // = Override all the ACE_Event_Handler methods and have them call + // through to the <T> operations handler. + virtual ACE_HANDLE get_handle (void) const; + virtual void set_handle (ACE_HANDLE); + virtual int handle_input (ACE_HANDLE fd = -1); + virtual int handle_output (ACE_HANDLE fd = -1); + virtual int handle_exception (ACE_HANDLE fd = -1); + virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg = 0); + virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask close_mask); + virtual int handle_signal (ACE_HANDLE signum, siginfo_t * = 0, ucontext_t * = 0); + + // = Get/set the operations handler. + T *op_handler (void); + void op_handler (T *); + + // = Get/set the target pointer-to-member-function used for + // dispatching. + + GET_HANDLE handle_get (void); + void handle_get (GET_HANDLE); + + SET_HANDLE handle_set (void); + void handle_set (SET_HANDLE); + + IO_HANDLER input_handler (void); + void input_handler (IO_HANDLER); + + IO_HANDLER output_handler (void); + void output_handler (IO_HANDLER); + + IO_HANDLER except_handler (void); + void except_handler (IO_HANDLER); + + TO_HANDLER to_handler (void); + void to_handler (TO_HANDLER); + + CL_HANDLER cl_handler (void); + void cl_handler (CL_HANDLER); + + SIG_HANDLER sig_handler (void); + void sig_handler (SIG_HANDLER); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + T *op_handler_; + // Pointer to the object that handles all the delegated operations. + + // = Handle input, output, and exception events. + IO_HANDLER input_handler_; + IO_HANDLER output_handler_; + IO_HANDLER except_handler_; + + TO_HANDLER to_handler_; + // Handle timeout events. + + CL_HANDLER cl_handler_; + // Handle close events. + + SIG_HANDLER sig_handler_; + // Handle signal events. + + int delete_handler_; + // Keeps track of whether we need to delete the handler in the + // destructor. + + // = Get/set underlying handle. + SET_HANDLE set_handle_; + GET_HANDLE get_handle_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Event_Handler_T.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ +#endif /* ACE_EVENT_HANDLER_H */ diff --git a/ace/Event_Handler_T.i b/ace/Event_Handler_T.i new file mode 100644 index 00000000000..2f7b5e6deb7 --- /dev/null +++ b/ace/Event_Handler_T.i @@ -0,0 +1,187 @@ +/* -*- C++ -*- */ +// $Id$ + +// Event_Handler_T.i + +template<class T> void ACE_INLINE +ACE_Event_Handler_T<T>::op_handler (T *op) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::op_handler"); + this->op_handler_ = op; +} + +template<class T> ACE_INLINE T * +ACE_Event_Handler_T<T>::op_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::op_handler"); + return this->op_handler_; +} + +template<class T> ACE_HANDLE ACE_INLINE +ACE_Event_Handler_T<T>::get_handle (void) const +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::get_handle"); + return this->get_handle_ == 0 ? -1 : (this->op_handler_->*get_handle_) (); +} + +template<class T> void ACE_INLINE +ACE_Event_Handler_T<T>::set_handle (ACE_HANDLE h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::set_handle"); + if (this->set_handle_ != 0) + (this->op_handler_->*set_handle_) (h); +} + +template<class T> int ACE_INLINE +ACE_Event_Handler_T<T>::handle_input (ACE_HANDLE fd) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_input"); + return this->input_handler_ == 0 ? 0 : (this->op_handler_->*input_handler_) (fd); +} + +template<class T> int ACE_INLINE +ACE_Event_Handler_T<T>::handle_output (ACE_HANDLE fd) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_output"); + return this->output_handler_ == 0 ? 0 : (this->op_handler_->*output_handler_) (fd); +} + +template<class T> ACE_INLINE int +ACE_Event_Handler_T<T>::handle_exception (ACE_HANDLE fd) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_exception"); + return this->except_handler_ == 0 ? 0 : (this->op_handler_->*except_handler_) (fd); +} + +template<class T> ACE_INLINE int +ACE_Event_Handler_T<T>::handle_timeout (const ACE_Time_Value &tv, const void *arg) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_timeout"); + return this->to_handler_ == 0 ? 0 : (this->op_handler_->*to_handler_) (tv, arg); +} + +template<class T> ACE_INLINE int +ACE_Event_Handler_T<T>::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask close_mask) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_close"); + return this->cl_handler_ == 0 ? 0 : (this->op_handler_->*cl_handler_) (fd, close_mask); +} + +template<class T> ACE_INLINE int +ACE_Event_Handler_T<T>::handle_signal (ACE_HANDLE signum, siginfo_t *s, ucontext_t *u) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_signal"); + return this->sig_handler_ == 0 ? 0 : (this->op_handler_->*sig_handler_) (signum, s, u); +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::GET_HANDLE +ACE_Event_Handler_T<T>::handle_get (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_get"); + return this->get_handle_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::handle_get (ACE_Event_Handler_T<T>::GET_HANDLE h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_get"); + this->get_handle_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::SET_HANDLE +ACE_Event_Handler_T<T>::handle_set (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_set"); + return this->set_handle_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::handle_set (ACE_Event_Handler_T<T>::SET_HANDLE h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::handle_set"); + this->set_handle_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::IO_HANDLER +ACE_Event_Handler_T<T>::input_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::input_handler"); + return this->input_handler_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::input_handler (ACE_Event_Handler_T<T>::IO_HANDLER h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::input_handler"); + this->input_handler_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::IO_HANDLER +ACE_Event_Handler_T<T>::output_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::output_handler"); + return this->output_handler_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::output_handler (ACE_Event_Handler_T<T>::IO_HANDLER h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::output_handler"); + this->output_handler_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::IO_HANDLER +ACE_Event_Handler_T<T>::except_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::except_handler"); + return this->except_handler_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::except_handler (ACE_Event_Handler_T<T>::IO_HANDLER h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::except_handler"); + this->except_handler_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::TO_HANDLER +ACE_Event_Handler_T<T>::to_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::to_handler"); + return this->to_handler_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::to_handler (ACE_Event_Handler_T<T>::TO_HANDLER h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::to_handler"); + this->to_handler_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::CL_HANDLER +ACE_Event_Handler_T<T>::cl_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::cl_handler"); + return this->cl_handler_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::cl_handler (ACE_Event_Handler_T<T>::CL_HANDLER h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::cl_handler"); + this->cl_handler_ = h; +} + +template<class T> ACE_INLINE ACE_Event_Handler_T<T>::SIG_HANDLER +ACE_Event_Handler_T<T>::sig_handler (void) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::sig_handler"); + return this->sig_handler_; +} + +template<class T> ACE_INLINE void +ACE_Event_Handler_T<T>::sig_handler (ACE_Event_Handler_T<T>::SIG_HANDLER h) +{ + ACE_TRACE ("ACE_Event_Handler_T<T>::sig_handler"); + this->sig_handler_ = h; +} diff --git a/ace/FIFO.cpp b/ace/FIFO.cpp new file mode 100644 index 00000000000..8c1f4d1b980 --- /dev/null +++ b/ace/FIFO.cpp @@ -0,0 +1,67 @@ +// FIFO.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/FIFO.h" + +#if !defined (__ACE_INLINE__) +#include "ace/FIFO.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_FIFO) + +void +ACE_FIFO::dump (void) const +{ + ACE_TRACE ("ACE_FIFO::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "rendezvous_ = %s", this->rendezvous_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_FIFO::open (const char *r, int flags, int perms) +{ + ACE_TRACE ("ACE_FIFO::open"); + ACE_OS::strncpy (this->rendezvous_, r, MAXPATHLEN); + + if ((flags & O_CREAT) != 0 + && ACE_OS::mkfifo (this->rendezvous_, perms) == -1 + && !(errno == EEXIST)) + return -1; + + this->set_handle (ACE_OS::open (this->rendezvous_, flags)); + return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0; +} + +ACE_FIFO::ACE_FIFO (const char *fifo_name, + int flags, + int perms) +{ + ACE_TRACE ("ACE_FIFO::ACE_FIFO"); + if (this->open (fifo_name, flags, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_FIFO")); +} + +ACE_FIFO::ACE_FIFO (void) +{ +// ACE_TRACE ("ACE_FIFO::ACE_FIFO"); +} + +int +ACE_FIFO::close (void) +{ + ACE_TRACE ("ACE_FIFO::close"); + int result = 0; + + if (this->get_handle () != ACE_INVALID_HANDLE) + { + result = ACE_OS::close (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + } + return result; +} + diff --git a/ace/FIFO.h b/ace/FIFO.h new file mode 100644 index 00000000000..dc4ffac7f40 --- /dev/null +++ b/ace/FIFO.h @@ -0,0 +1,66 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FIFO.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FIFO_H) +#define ACE_FIFO_H + +#include "ace/IPC_SAP.h" + +class ACE_Export ACE_FIFO : public ACE_IPC_SAP + // = TITLE + // Abstract base class for UNIX FIFOs (a.k.a. Named Pipes). +{ +public: + int open (const char *rendezvous, int flags, int perms); + // Open up the named pipe on the <rendezvous> in accordance with the + // flags. + + int close (void); + // Close down the ACE_FIFO without removing the rendezvous point. + + int remove (void); + // Close down the ACE_FIFO and remove the rendezvous point from the + // file system. + + int get_local_addr (const char *&rendezvous) const; + // Return the local address of this endpoint. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Make these protected to ensure that the class is "abstract." + ACE_FIFO (void); + // Default constructor. + + ACE_FIFO (const char *rendezvous, int flags, int perms); + // Open up the named pipe on the <rendezvous> in accordance with the + // flags. + +private: + char rendezvous_[MAXPATHLEN + 1]; + // Rendezvous point in the file system. +}; + +#if defined (__ACE_INLINE__) +#include "ace/FIFO.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_FIFO_H */ diff --git a/ace/FIFO.i b/ace/FIFO.i new file mode 100644 index 00000000000..be1481b954a --- /dev/null +++ b/ace/FIFO.i @@ -0,0 +1,23 @@ +/* -*- C++ -*- */ +// $Id$ + +// FIFO.i + +#include "ace/Log_Msg.h" + +ACE_INLINE int +ACE_FIFO::get_local_addr (const char *&r) const +{ + ACE_TRACE ("ACE_FIFO::get_local_addr"); + r = this->rendezvous_; + return 0; +} + +ACE_INLINE int +ACE_FIFO::remove (void) +{ + ACE_TRACE ("ACE_FIFO::remove"); + int result = this->close (); + return ACE_OS::unlink (this->rendezvous_) == -1 || result == -1 ? -1 : 0; +} + diff --git a/ace/FIFO_Recv.cpp b/ace/FIFO_Recv.cpp new file mode 100644 index 00000000000..ff05686d6a1 --- /dev/null +++ b/ace/FIFO_Recv.cpp @@ -0,0 +1,63 @@ +// FIFO_Recv.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/FIFO_Recv.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Recv) + +void +ACE_FIFO_Recv::dump (void) const +{ + ACE_TRACE ("ACE_FIFO_Recv::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_FIFO::dump (); + ACE_DEBUG ((LM_DEBUG, "aux_handle_ = %d", this->aux_handle_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_FIFO_Recv::close (void) +{ + ACE_TRACE ("ACE_FIFO_Recv::close"); + int result = ACE_FIFO::close (); + if (this->aux_handle_ != ACE_INVALID_HANDLE) + return ACE_OS::close (this->aux_handle_); + else + return result; +} + +// Note that persistent means "open fifo for writing, as well as +// reading." This ensures that the fifo never gets EOF, even if there +// aren't any writers at the moment! + +int +ACE_FIFO_Recv::open (const char *fifo_name, int flags, int perms, int persistent) +{ + ACE_TRACE ("ACE_FIFO_Recv::open"); + if (ACE_FIFO::open (fifo_name, ACE_NONBLOCK | flags, perms) == -1) + return -1; + else if (this->disable (ACE_NONBLOCK) == -1) + return -1; + else if (persistent && (this->aux_handle_ = + ACE_OS::open (fifo_name, O_WRONLY)) == ACE_INVALID_HANDLE) + return -1; + else + return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0; +} + +ACE_FIFO_Recv::ACE_FIFO_Recv (void): aux_handle_ (ACE_INVALID_HANDLE) +{ + ACE_TRACE ("ACE_FIFO_Recv::ACE_FIFO_Recv"); +} + +ACE_FIFO_Recv::ACE_FIFO_Recv (const char *fifo_name, int flags, int perms, int persistent) +{ + ACE_TRACE ("ACE_FIFO_Recv::ACE_FIFO_Recv"); + if (this->ACE_FIFO_Recv::open (fifo_name, flags, perms, persistent) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_FIFO_Recv")); +} + diff --git a/ace/FIFO_Recv.h b/ace/FIFO_Recv.h new file mode 100644 index 00000000000..046ec39db0a --- /dev/null +++ b/ace/FIFO_Recv.h @@ -0,0 +1,67 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FIFO_Recv.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FIFO_RECV_H) +#define ACE_FIFO_RECV_H + +#include "ace/FIFO.h" + +class ACE_Export ACE_FIFO_Recv : public ACE_FIFO + // = TITLE + // Receiver side of the bytestream C++ wrapper for UNIX + // FIFOs. +{ +public: + // = Initialization methods. + ACE_FIFO_Recv (void); + // Default constructor. + + ACE_FIFO_Recv (const char *rendezvous, + int flags = O_CREAT | O_RDONLY, + int perms = ACE_DEFAULT_PERMS, + int persistent = 1); + // Open up a bytestream named pipe for reading. + + int open (const char *rendezvous, + int flags = O_CREAT | O_RDONLY, + int perms = ACE_DEFAULT_PERMS, + int persistent = 1); + // Open up a bytestream named pipe for reading. + + int close (void); + // Close down the named pipe. + + ssize_t recv (void *buf, size_t len); + // Recv <buf> of up to <len> bytes. + + ssize_t recv_n (void *buf, size_t len); + // Recv <buf> of exactly <len> bytes (block until done). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_HANDLE aux_handle_; + // Auxiliary handle that is used to implement persistent FIFOs. +}; + +#include "ace/FIFO_Recv.i" + +#endif /* ACE_FIFO_RECV_H */ diff --git a/ace/FIFO_Recv.i b/ace/FIFO_Recv.i new file mode 100644 index 00000000000..51ae81efca8 --- /dev/null +++ b/ace/FIFO_Recv.i @@ -0,0 +1,18 @@ +/* -*- C++ -*- */ +// $Id$ + +// FIFO_Recv.i + +inline ssize_t +ACE_FIFO_Recv::recv (void *buf, size_t len) +{ + ACE_TRACE ("ACE_FIFO_Recv::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, len); +} + +inline ssize_t +ACE_FIFO_Recv::recv_n (void *buf, size_t n) +{ + ACE_TRACE ("ACE_FIFO_Recv::recv_n"); + return ACE::recv_n (this->get_handle (), buf, n); +} diff --git a/ace/FIFO_Recv_Msg.cpp b/ace/FIFO_Recv_Msg.cpp new file mode 100644 index 00000000000..002efd735a9 --- /dev/null +++ b/ace/FIFO_Recv_Msg.cpp @@ -0,0 +1,41 @@ +// FIFO_Recv_Msg.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/FIFO_Recv_Msg.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Recv_Msg) + +void +ACE_FIFO_Recv_Msg::dump (void) const +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::dump"); + ACE_FIFO_Recv::dump (); +} + +/* Note that persistent means "open fifo for writing, as well as reading." + This ensures that the fifo never gets EOF, even if there aren't + any writers at the moment! */ + +int +ACE_FIFO_Recv_Msg::open (const char *fifo_name, int flags, int perms, int persistent) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::open"); + return ACE_FIFO_Recv::open (fifo_name, flags, perms, persistent); +} + +ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg (void) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg"); +} + +ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg (const char *fifo_name, int flags, int perms, int persistent) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::ACE_FIFO_Recv_Msg"); + if (this->ACE_FIFO_Recv_Msg::open (fifo_name, flags, perms, + persistent) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_FIFO_Recv_Msg")); +} diff --git a/ace/FIFO_Recv_Msg.h b/ace/FIFO_Recv_Msg.h new file mode 100644 index 00000000000..d3d3109134b --- /dev/null +++ b/ace/FIFO_Recv_Msg.h @@ -0,0 +1,72 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FIFO_Recv_Msg.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FIFO_RECV_MSG_H) +#define ACE_FIFO_RECV_MSG_H + +#include "ace/FIFO_Recv.h" + +class ACE_Export ACE_FIFO_Recv_Msg : public ACE_FIFO_Recv + // = TITLE + // Receiver side for the record oriented C++ wrapper for UNIX FIFOs. +{ +public: + // = Initialization methods. + ACE_FIFO_Recv_Msg (void); + // Default constructor. + + ACE_FIFO_Recv_Msg (const char *rendezvous, + int flags = O_CREAT | O_RDONLY, + int perms = ACE_DEFAULT_PERMS, + int persistent = 1); + // Open up a record-oriented named pipe for reading. + + int open (const char *rendezvous, + int flags = O_CREAT | O_RDONLY, + int perms = ACE_DEFAULT_PERMS, + int persistent = 1); + // Open up a record-oriented named pipe for reading. + + ssize_t recv (ACE_Str_Buf &msg); + // Recv <msg> as an ACE_Str_Buf. + + ssize_t recv (void *buf, size_t len); + // Recv <msg> as a buffer. + +#if defined (ACE_HAS_STREAM_PIPES) + ssize_t recv (ACE_Str_Buf *data, + ACE_Str_Buf *cntl, + int *flags); + // Recv <data> and <cntl> message via Stream pipes. + + ssize_t recv (int *band, + ACE_Str_Buf *data, + ACE_Str_Buf *cntl, + int *flags); + // Recv <data> and <cntl> message via Stream pipes in "band" mode. +#endif /* ACE_HAS_STREAM_PIPES */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/FIFO_Recv_Msg.i" + +#endif /* ACE_FIFO_RECV_MSG_H */ diff --git a/ace/FIFO_Recv_Msg.i b/ace/FIFO_Recv_Msg.i new file mode 100644 index 00000000000..7ee7f74ee10 --- /dev/null +++ b/ace/FIFO_Recv_Msg.i @@ -0,0 +1,55 @@ +/* -*- C++ -*- */ +// $Id$ + +// FIFO_Recv_Msg.i + +// Note that the return values mean different things if +// ACE_HAS_STREAM_PIPES vs. if it doesn't... See the manual page on +// getmsg(2) and read(2) for more details. + +inline ssize_t +ACE_FIFO_Recv_Msg::recv (ACE_Str_Buf &recv_msg) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::recv"); +#if defined (ACE_HAS_STREAM_PIPES) + int i = 0; + return ACE_OS::getmsg (this->get_handle (), (strbuf *) 0, (strbuf *) &recv_msg, &i); +#else /* Do the ol' 2-read trick... */ + if (ACE_OS::read (this->get_handle (), + (char *) &recv_msg.len, + sizeof recv_msg.len) != sizeof recv_msg.len) + return -1; + else + return ACE_OS::read (this->get_handle (), + (char *) recv_msg.buf, + (int) recv_msg.len); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +inline ssize_t +ACE_FIFO_Recv_Msg::recv (void *buf, size_t max_len) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::recv"); + ACE_Str_Buf recv_msg ((char *) buf, 0, max_len); + + return this->recv (recv_msg); +} + +#if defined (ACE_HAS_STREAM_PIPES) +inline ssize_t +ACE_FIFO_Recv_Msg::recv (ACE_Str_Buf *data, ACE_Str_Buf *cntl, int *flags) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::recv"); + return ACE_OS::getmsg (this->get_handle (), + (strbuf *) cntl, (strbuf *) data, flags); +} + +inline ssize_t +ACE_FIFO_Recv_Msg::recv (int *band, ACE_Str_Buf *data, ACE_Str_Buf *cntl, int *flags) +{ + ACE_TRACE ("ACE_FIFO_Recv_Msg::recv"); + return ACE_OS::getpmsg (this->get_handle (), + (strbuf *) cntl, (strbuf *) data, band, flags); +} + +#endif /* ACE_HAS_STREAM_PIPES */ diff --git a/ace/FIFO_Send.cpp b/ace/FIFO_Send.cpp new file mode 100644 index 00000000000..6d463af5ae8 --- /dev/null +++ b/ace/FIFO_Send.cpp @@ -0,0 +1,36 @@ +// FIFO_Send.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/FIFO_Send.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Send) + +void +ACE_FIFO_Send::dump (void) const +{ + ACE_TRACE ("ACE_FIFO_Send::dump"); + ACE_FIFO::dump (); +} + +ACE_FIFO_Send::ACE_FIFO_Send (void) +{ +// ACE_TRACE ("ACE_FIFO_Send::ACE_FIFO_Send"); +} + +int +ACE_FIFO_Send::open (const char *rendezvous_name, int flags, int perms) +{ + ACE_TRACE ("ACE_FIFO_Send::open"); + return ACE_FIFO::open (rendezvous_name, flags | O_WRONLY, perms); +} + +ACE_FIFO_Send::ACE_FIFO_Send (const char *fifo_name, int flags, int perms) +{ + ACE_TRACE ("ACE_FIFO_Send::ACE_FIFO_Send"); + if (this->ACE_FIFO_Send::open (fifo_name, flags, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_FIFO_Send::ACE_FIFO_Send")); +} diff --git a/ace/FIFO_Send.h b/ace/FIFO_Send.h new file mode 100644 index 00000000000..c413ed12635 --- /dev/null +++ b/ace/FIFO_Send.h @@ -0,0 +1,58 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FIFO_Send.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FIFO_SEND_H) +#define ACE_FIFO_SEND_H + +#include "ace/FIFO.h" + +class ACE_Export ACE_FIFO_Send : public ACE_FIFO + // = TITLE + // Sender side for the bytestream C++ wrapper for UNIX FIFOs +{ +public: + // = Initialization methods. + ACE_FIFO_Send (void); + // Default constructor. + + ACE_FIFO_Send (const char *rendezvous, + int flags = O_WRONLY, + int perms = ACE_DEFAULT_PERMS); + // Open up a bytestream named pipe for writing. + + int open (const char *rendezvous, + int flags = O_WRONLY, + int perms = ACE_DEFAULT_PERMS); + // Open up a bytestream named pipe for writing. + + ssize_t send (const void *buf, size_t len); + // Send <buf> of up to <len> bytes. + + ssize_t send_n (const void *buf, size_t len); + // Send <buf> of exactly <len> bytes (block until done). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/FIFO_Send.i" + +#endif /* ACE_FIFO_SEND_H */ + diff --git a/ace/FIFO_Send.i b/ace/FIFO_Send.i new file mode 100644 index 00000000000..5785229f167 --- /dev/null +++ b/ace/FIFO_Send.i @@ -0,0 +1,18 @@ +/* -*- C++ -*- */ +// $Id$ + +// FIFO_Send.i + +inline ssize_t +ACE_FIFO_Send::send (const void *buf, size_t len) +{ + ACE_TRACE ("ACE_FIFO_Send::send"); + return ACE_OS::write (this->get_handle (), (const char *) buf, len); +} + +inline ssize_t +ACE_FIFO_Send::send_n (const void *buf, size_t n) +{ + ACE_TRACE ("ACE_FIFO_Send::send_n"); + return ACE::send_n (this->get_handle (), buf, n); +} diff --git a/ace/FIFO_Send_Msg.cpp b/ace/FIFO_Send_Msg.cpp new file mode 100644 index 00000000000..88848c779ca --- /dev/null +++ b/ace/FIFO_Send_Msg.cpp @@ -0,0 +1,62 @@ +// FIFO_Send_Msg.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/FIFO_Send_Msg.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FIFO_Send_Msg) + +void +ACE_FIFO_Send_Msg::dump (void) const +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::dump"); + ACE_FIFO_Send::dump (); +} + +ssize_t +ACE_FIFO_Send_Msg::send (const ACE_Str_Buf &send_msg) +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::send"); +#if defined (ACE_HAS_STREAM_PIPES) + return ACE_OS::putmsg (this->get_handle (), + (strbuf *) 0, + (strbuf *) &send_msg, + 0); +#else + struct iovec iov[2]; + + iov[0].iov_base = (char *) &send_msg.len; + iov[0].iov_len = sizeof send_msg.len; + + iov[1].iov_base = (char *) send_msg.buf; + iov[1].iov_len = int (send_msg.len); + + return ACE_OS::writev (this->get_handle (), iov, 2); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg (void) +{ +// ACE_TRACE ("ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg"); +} + +int +ACE_FIFO_Send_Msg::open (const char *fifo_name, + int flags, + int perms) +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::open"); + return ACE_FIFO_Send::open (fifo_name, flags | O_WRONLY, perms); +} + +ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg (const char *fifo_name, + int flags, + int perms) +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::ACE_FIFO_Send_Msg"); + if (this->ACE_FIFO_Send_Msg::open (fifo_name, flags, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_FIFO_Send_Msg")); +} diff --git a/ace/FIFO_Send_Msg.h b/ace/FIFO_Send_Msg.h new file mode 100644 index 00000000000..8898bc320f9 --- /dev/null +++ b/ace/FIFO_Send_Msg.h @@ -0,0 +1,72 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FIFO_Send_Msg.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FIFO_SEND_MSG_H) +#define ACE_FIFO_SEND_MSG_H + +#include "ace/FIFO_Send.h" + +class ACE_Export ACE_FIFO_Send_Msg : public ACE_FIFO_Send + // = TITLE + // Sender side for the Record oriented C++ wrapper for UNIX + // FIFOs. +{ +public: + // = Initialization methods. + ACE_FIFO_Send_Msg (void); + // Default constructor. + + ACE_FIFO_Send_Msg (const char *rendezvous, + int flags = O_WRONLY, + int perms = ACE_DEFAULT_PERMS); + // Open up a record-oriented named pipe for writing. + + int open (const char *rendezvous, + int flags = O_WRONLY, + int perms = ACE_DEFAULT_PERMS); + // Open up a record-oriented named pipe for writing. + + ssize_t send (const ACE_Str_Buf &msg); + // Send <buf> of up to <len> bytes. + + ssize_t send (const void *buf, size_t len); + // Send <buf> of exactly <len> bytes (block until done). + +#if defined (ACE_HAS_STREAM_PIPES) + ssize_t send (const ACE_Str_Buf *data, + const ACE_Str_Buf *cntl = 0, + int flags = 0); + // Send <data> and <cntl> message via Stream pipes. + + ssize_t send (int band, + const ACE_Str_Buf *data, + const ACE_Str_Buf *cntl = 0, + int flags = MSG_BAND); + // Send <data> and <cntl> message via Stream pipes in "band" mode. +#endif /* ACE_HAS_STREAM_PIPES */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/FIFO_Send_Msg.i" + +#endif /* ACE_FIFO_SEND_MSG_H */ + diff --git a/ace/FIFO_Send_Msg.i b/ace/FIFO_Send_Msg.i new file mode 100644 index 00000000000..7d6b767cc4b --- /dev/null +++ b/ace/FIFO_Send_Msg.i @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ +// $Id$ + +// FIFO_Send_Msg.i + +inline ssize_t +ACE_FIFO_Send_Msg::send (const void *buf, size_t len) +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::send"); + ACE_Str_Buf send_msg ((char *) buf, len); + + return this->send (send_msg); +} + +#if defined (ACE_HAS_STREAM_PIPES) +inline ssize_t +ACE_FIFO_Send_Msg::send (const ACE_Str_Buf *data, + const ACE_Str_Buf *cntl, + int flags) +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::send"); + return ACE_OS::putmsg (this->get_handle (), + (strbuf *) cntl, + (strbuf *) data, + flags); +} + +inline ssize_t +ACE_FIFO_Send_Msg::send (int band, + const ACE_Str_Buf *data, + const ACE_Str_Buf *cntl, + int flags) +{ + ACE_TRACE ("ACE_FIFO_Send_Msg::send"); + return ACE_OS::putpmsg (this->get_handle (), + (strbuf *) cntl, + (strbuf *) data, + band, + flags); +} +#endif /* ACE_HAS_STREAM_PIPES */ diff --git a/ace/FILE.cpp b/ace/FILE.cpp new file mode 100644 index 00000000000..a6928173f98 --- /dev/null +++ b/ace/FILE.cpp @@ -0,0 +1,72 @@ +// FILE.cpp +// $Id$ + +/* Defines the member functions for the base class of the ACE_IO_SAP + ACE_FILE abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/FILE.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FILE) + +void +ACE_FILE::dump (void) const +{ + ACE_TRACE ("ACE_FILE::dump"); + ACE_IO_SAP::dump (); +} + +/* This is the do-nothing constructor. */ + +ACE_FILE::ACE_FILE (void) +{ + ACE_TRACE ("ACE_FILE::ACE_FILE"); +} + +// Close the file + +int +ACE_FILE::close (void) +{ + ACE_TRACE ("ACE_FILE::close"); + int result = ACE_OS::close (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + return result; +} + +int +ACE_FILE::get_info (ACE_FILE_Info *finfo) +{ + ACE_TRACE ("ACE_FILE::get_info"); + struct stat filestatus; + int result = ACE_OS::fstat (this->get_handle (), &filestatus); + + if (result == 0) + { + finfo->mode_ = filestatus.st_mode; + finfo->nlink_ = filestatus.st_nlink; + finfo->size_ = filestatus.st_size; + } + return result; +} + +int +ACE_FILE::truncate (off_t length) +{ + ACE_TRACE ("ACE_FILE::truncate"); + return ACE_OS::ftruncate (this->get_handle(), length); +} + +off_t +ACE_FILE::position (long offset, int startpos) +{ + ACE_TRACE ("ACE_FILE::position"); + return ACE_OS::lseek (this->get_handle (), offset, startpos); +} + +off_t +ACE_FILE::position (void) +{ + ACE_TRACE ("ACE_FILE::position"); + return ACE_OS::lseek (this->get_handle (), 0, SEEK_CUR); +} diff --git a/ace/FILE.h b/ace/FILE.h new file mode 100644 index 00000000000..778fd95b925 --- /dev/null +++ b/ace/FILE.h @@ -0,0 +1,83 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FILE.h +// +// = AUTHOR +// Gerhard Lenzer +// +// ============================================================================ + +#if !defined (ACE_FILE_H) +#define ACE_FILE_H + +#include "ace/IO_SAP.h" +#include "ace/FILE_Addr.h" + +// 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) +#define ACE_FILE_CONNECTOR ACE_FILE_Connector +#define ACE_FILE_STREAM ACE_FILE_Stream +#else /* TEMPLATES are broken (must be a cfront-based compiler...) */ +#define ACE_FILE_CONNECTOR ACE_FILE_Connector, ACE_FILE_Addr +#define ACE_FILE_STREAM ACE_FILE_Stream, ACE_FILE_Addr +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +struct ACE_FILE_Info +{ + mode_t mode_; + // mode of file + + nlink_t nlink_; + // no of links + + off_t size_; + // size of file +}; + +class ACE_Export ACE_FILE : public ACE_IO_SAP + // = TITLE + // Defines the member functions for the base class of the + // ACE_FILE abstraction. +{ +public: + int close (void); + // Close down the ACE_FILE + + int get_info (ACE_FILE_Info *finfo); + // get informations on the ACE_FILE + + int truncate (off_t length); + // set filesize to length byte + + off_t position (long offset, int startpos); + // set the filepointer to the specified position + + off_t position (void); + // get current filepointer + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_FILE (void); + // Ensure that this class is an abstract base class +}; + +#include "ace/FILE.i" + +#endif /* ACE_FILE_H */ diff --git a/ace/FILE.i b/ace/FILE.i new file mode 100644 index 00000000000..961d2bdc766 --- /dev/null +++ b/ace/FILE.i @@ -0,0 +1,6 @@ +/* -*- C++ -*- */ +// $Id$ + +// FILE.i + + diff --git a/ace/FILE_Addr.cpp b/ace/FILE_Addr.cpp new file mode 100644 index 00000000000..3ff02900990 --- /dev/null +++ b/ace/FILE_Addr.cpp @@ -0,0 +1,23 @@ +// FILE_Addr.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/FILE_Addr.h" + +#if !defined (__ACE_INLINE__) +#include "ace/FILE_Addr.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_FILE_Addr) + +void +ACE_FILE_Addr::dump (void) const +{ + ACE_TRACE ("ACE_FILE_Addr::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "filename_ = %s", this->filename_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + diff --git a/ace/FILE_Addr.h b/ace/FILE_Addr.h new file mode 100644 index 00000000000..978ea3e0608 --- /dev/null +++ b/ace/FILE_Addr.h @@ -0,0 +1,75 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FILE_Addr.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FILE_ADDR_H) +#define ACE_FILE_ADDR_H + +#include "ace/Addr.h" +#include "ace/ACE.h" + +class ACE_Export ACE_FILE_Addr : public ACE_Addr + // = TITLE + // Defines the FILE address family address format. +{ +public: + // = Initialization methods. + ACE_FILE_Addr (void); + // Default constructor. + + ACE_FILE_Addr (const ACE_FILE_Addr &sa); + // Copy constructor. + + ACE_FILE_Addr (LPCTSTR filename); + // Create a ACE_FILE_Addr from a pathname. + + void set (LPCTSTR filename); + // Create a ACE_FILE_Addr from a pathname. + + ACE_FILE_Addr &operator= (const ACE_FILE_Addr &); + // Assignment operator. + + virtual void *get_addr (void) const; + // Return a pointer to the address. + + virtual int addr_to_string (char addr[], size_t) const; + // Transform the current address into string format. + + virtual int operator == (const ACE_Addr &SAP) const; + // Compare two addresses for equality. + + virtual int operator != (const ACE_Addr &SAP) const; + // Compare two addresses for inequality. + + LPCTSTR get_path_name (void) const; + // Return the path name used for the rendezvous point. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + TCHAR filename_[MAXNAMLEN + 1]; + // Name of the file. +}; + +#if defined (__ACE_INLINE__) +#include "ace/FILE_Addr.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_FILE_ADDR_H */ diff --git a/ace/FILE_Addr.i b/ace/FILE_Addr.i new file mode 100644 index 00000000000..c6237feac46 --- /dev/null +++ b/ace/FILE_Addr.i @@ -0,0 +1,93 @@ +/* -*- C++ -*- */ +// $Id$ + +// FILE_Addr.i + +// Do nothing constructor. + +ACE_INLINE +ACE_FILE_Addr::ACE_FILE_Addr (void) + : ACE_Addr (AF_FILE, sizeof this->filename_) +{ + (void) ACE_OS::memset ((void *) &this->filename_, + 0, sizeof this->filename_); +} + +// Copy constructor. + +ACE_INLINE +ACE_FILE_Addr::ACE_FILE_Addr (const ACE_FILE_Addr &sa) + : ACE_Addr (AF_FILE, ACE_OS::strlen (sa.filename_)) +{ + (void) ACE_OS::memcpy ((void *) &this->filename_, + (void *) &sa.filename_, sa.get_size ()); +} + +ACE_INLINE ACE_FILE_Addr & +ACE_FILE_Addr::operator= (const ACE_FILE_Addr &sa) +{ + if (this != &sa) + (void) ACE_OS::memcpy ((void *) &this->filename_, + (void *) &sa.filename_, + sa.get_size ()); + return *this; +} + +ACE_INLINE void +ACE_FILE_Addr::set (LPCTSTR filename) +{ + + this->ACE_Addr::base_set (AF_FILE, ACE_OS::strlen (filename) ); + (void) ACE_OS::strcpy (this->filename_, filename); +} + +// Create a ACE_Addr from a ACE_FILE pathname. + +ACE_INLINE +ACE_FILE_Addr::ACE_FILE_Addr (LPCTSTR filename) +{ + this->set (filename); +} + +// Transform the current address into string format. + +ACE_INLINE int +ACE_FILE_Addr::addr_to_string (char s[], size_t len) const +{ + ACE_OS::strncpy (s, this->filename_, len); + return 0; +} + +// Return the address. + +ACE_INLINE void * +ACE_FILE_Addr::get_addr (void) const +{ + return (void *) &this->filename_; +} + +// Compare two addresses for equality. + +ACE_INLINE int +ACE_FILE_Addr::operator == (const ACE_Addr &sap) const +{ + return ACE_OS::strcmp (this->filename_, + ((ACE_FILE_Addr &) sap).filename_) == 0; +} + +// Compare two addresses for inequality. + +ACE_INLINE int +ACE_FILE_Addr::operator != (const ACE_Addr &sap) const +{ + return !((*this) == sap); // This is lazy, of course... ;-) +} + +// Return the path name used for the rendezvous point. + +ACE_INLINE LPCTSTR +ACE_FILE_Addr::get_path_name (void) const +{ + return this->filename_; +} + diff --git a/ace/FILE_Connector.cpp b/ace/FILE_Connector.cpp new file mode 100644 index 00000000000..7ddf41e4506 --- /dev/null +++ b/ace/FILE_Connector.cpp @@ -0,0 +1,43 @@ +// FILE_Connector.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/FILE_Connector.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FILE_Connector) + +void +ACE_FILE_Connector::dump (void) const +{ + ACE_TRACE ("ACE_FILE_Connector::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_FILE_Connector::ACE_FILE_Connector (void) +{ + ACE_TRACE ("ACE_FILE_Connector::ACE_FILE_Connector"); +} + +int +ACE_FILE_Connector::connect (ACE_FILE_IO &new_io, + const ACE_FILE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &, + int, + int flags, + int perms) +{ + ACE_TRACE ("ACE_FILE_Connector::connect"); + ACE_ASSERT (new_io.get_handle () == ACE_INVALID_HANDLE); + + ACE_HANDLE handle = ACE::handle_timed_open (timeout, + remote_sap.get_path_name (), + flags, perms); + new_io.set_handle (handle); + new_io.remote_addr_ = remote_sap; // class copy. + return handle == ACE_INVALID_HANDLE ? -1 : 0; +} + diff --git a/ace/FILE_Connector.h b/ace/FILE_Connector.h new file mode 100644 index 00000000000..0a36bde7764 --- /dev/null +++ b/ace/FILE_Connector.h @@ -0,0 +1,87 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FILE_Connector.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FILE_CONNECTOR_H) +#define ACE_FILE_CONNECTOR_H + +#include "ace/FILE_IO.h" + +class ACE_Export ACE_FILE_Connector : public ACE_FILE + // = TITLE + // Defines an active connection factory for the ACE_FILE wrappers. +{ +public: + // = Initialization methods. + ACE_FILE_Connector (void); + // Default constructor. + + ACE_FILE_Connector (ACE_FILE_IO &new_io, + const ACE_FILE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + int connect (ACE_FILE_IO &new_io, + const ACE_FILE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/FILE_Connector.i" + +#endif /* ACE_FILE_CONNECTOR_H */ diff --git a/ace/FILE_Connector.i b/ace/FILE_Connector.i new file mode 100644 index 00000000000..14e8d809a68 --- /dev/null +++ b/ace/FILE_Connector.i @@ -0,0 +1,25 @@ +/* -*- C++ -*- */ +// $Id$ + +// FILE_Connector.i + +#include "ace/Log_Msg.h" + +// Creates a Local ACE_FILE. + +inline +ACE_FILE_Connector::ACE_FILE_Connector (ACE_FILE_IO &new_io, + const ACE_FILE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_FILE_Connector::ACE_FILE_Connector"); + if (this->connect (new_io, remote_sap, timeout, local_sap, + reuse_addr, flags, perms) == ACE_IO_SAP::INVALID_HANDLE + && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + ACE_ERROR ((LM_ERROR, "address %s, %p\n", + remote_sap.get_path_name (), "ACE_FILE_IO")); +} diff --git a/ace/FILE_IO.cpp b/ace/FILE_IO.cpp new file mode 100644 index 00000000000..b77bcaf98fc --- /dev/null +++ b/ace/FILE_IO.cpp @@ -0,0 +1,100 @@ +// FILE_IO.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/FILE_IO.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_FILE_IO) + +void +ACE_FILE_IO::dump (void) const +{ + ACE_TRACE ("ACE_FILE_IO::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + remote_addr_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Simple-minded do nothing constructor. + +ACE_FILE_IO::ACE_FILE_IO (void) +{ + ACE_TRACE ("ACE_FILE_IO::ACE_FILE_IO"); +} + +// Send N char *ptrs and int lengths. Note that the char *'s precede +// the ints (basically, an varargs version of writev). The count N is +// the *total* number of trailing arguments, *not* a couple of the +// number of tuple pairs! + +ssize_t +ACE_FILE_IO::send (size_t n, ...) const +{ + ACE_TRACE ("ACE_FILE_IO::send"); + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::writev (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + +// This is basically an interface to ACE_OS::readv, that doesn't use +// the struct iovec explicitly. The ... can be passed as an arbitrary +// number of (char *ptr, int len) tuples. However, the count N is the +// *total* number of trailing arguments, *not* a couple of the number +// of tuple pairs! + +ssize_t +ACE_FILE_IO::recv (size_t n, ...) const +{ + ACE_TRACE ("ACE_FILE_IO::recv"); + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::readv (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + diff --git a/ace/FILE_IO.h b/ace/FILE_IO.h new file mode 100644 index 00000000000..436621ff518 --- /dev/null +++ b/ace/FILE_IO.h @@ -0,0 +1,109 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// FILE_IO.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_FILE_IO_H) +#define ACE_FILE_IO_H + +#include "ace/FILE.h" +#include "ace/FILE_Addr.h" + +class ACE_Export ACE_FILE_IO : public ACE_FILE + // = TITLE + // Read/Write operations on Files +{ +friend class ACE_FILE_Connector; +public: + // = Initialization method. + ACE_FILE_IO (void); + // Default constructor. + + ssize_t send (const void *buf, size_t n) const; + // send upto <n> bytes in <buf>. + + ssize_t recv (void *buf, size_t n) const; + // Recv upto <n> bytes in <buf>. + + ssize_t send_n (const void *buf, size_t n) const; + // Send n bytes, keep trying until n are sent. + + ssize_t recv_n (void *buf, size_t n) const; + // Recv n bytes, keep trying until n are received. + +#if defined (ACE_HAS_STREAM_PIPES) + ssize_t send (const ACE_Str_Buf *cntl, + const ACE_Str_Buf *data, + int flags = 0) const; + // Send bytes via STREAM pipes. + + ssize_t recv (ACE_Str_Buf *cntl, + ACE_Str_Buf *data, + int *flags) const; + // Recv bytes via STREAM pipes. + + ssize_t send (const ACE_Str_Buf *cntl, + const ACE_Str_Buf *data, + int band, + int flags = 0) const; + // Send bytes via STREAM pipes using "band" mode. + + ssize_t recv (ACE_Str_Buf *cntl, + ACE_Str_Buf *data, + int *band, + int *flags) const; + // Recv bytes via STREAM pipes using "band" mode. + +#endif /* ACE_HAS_STREAM_PIPES */ + + ssize_t send (const iovec iov[], size_t n) const; + // Send iovecs via <::writev>. + + ssize_t recv (iovec iov[], size_t n) const; + // Recv iovecs via <::readv>. + + ssize_t send (size_t n, ...) const; + // Send N char *ptrs and int lengths. Note that the char *'s + // precede the ints (basically, an varargs version of writev). The + // count N is the *total* number of trailing arguments, *not* a + // couple of the number of tuple pairs! + + ssize_t recv (size_t n, ...) const; + // This is an interface to ::readv, that doesn't use the struct + // iovec explicitly. The ... can be passed as an arbitrary number + // of (char *ptr, int len) tuples. However, the count N is the + // *total* number of trailing arguments, *not* a couple of the + // number of tuple pairs! + + ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Send <n> bytes via Win32 WriteFile using overlapped I/O. + + ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Recv <n> bytes via Win32 ReadFile using overlapped I/O. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_FILE_Addr remote_addr_; + // File we are "connected" with... +}; + +#include "ace/FILE_IO.i" + +#endif /* ACE_FILE_IO_H */ diff --git a/ace/FILE_IO.i b/ace/FILE_IO.i new file mode 100644 index 00000000000..fffffd1de1c --- /dev/null +++ b/ace/FILE_IO.i @@ -0,0 +1,101 @@ +/* -*- C++ -*- */ +// $Id$ + +// FILE_IO.i + +// Send exactly N bytes from BUF to this file. Keeping trying until +// this many bytes are sent. + +inline ssize_t +ACE_FILE_IO::send_n (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_FILE_IO::send_n"); + return ACE::send_n (this->get_handle (), buf, n); +} + +// Receive exactly N bytes from this file into BUF. Keep trying until +// this many bytes are received. + +inline ssize_t +ACE_FILE_IO::recv_n (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_FILE_IO::recv_n"); + return ACE::recv_n (this->get_handle (), buf, n); +} + +inline ssize_t +ACE_FILE_IO::send (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_FILE_IO::send"); + return ACE_OS::write (this->get_handle (), (const char *) buf, n); +} + +inline ssize_t +ACE_FILE_IO::recv (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_FILE_IO::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n); +} + +inline ssize_t +ACE_FILE_IO::send (const iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_FILE_IO::send"); + return ACE_OS::writev (this->get_handle (), (iovec *) iov, n); +} + +inline ssize_t +ACE_FILE_IO::recv (iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_FILE_IO::recv"); + return ACE_OS::readv (this->get_handle (), (iovec *) iov, n); +} + +#if defined (ACE_HAS_STREAM_PIPES) +inline ssize_t +ACE_FILE_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *band, int *flags) const +{ + ACE_TRACE ("ACE_FILE_IO::recv"); + return ACE_OS::getpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags); +} + +inline ssize_t +ACE_FILE_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int band, int flags) const +{ + ACE_TRACE ("ACE_FILE_IO::send"); + return ACE_OS::putpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags); +} + +inline ssize_t +ACE_FILE_IO::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *flags) const +{ + ACE_TRACE ("ACE_FILE_IO::recv"); + return ACE_OS::getmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags); +} + +inline ssize_t +ACE_FILE_IO::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int flags) const +{ + ACE_TRACE ("ACE_FILE_IO::send"); + return ACE_OS::putmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags); +} + +inline ssize_t +ACE_FILE_IO::send (const void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_FILE_IO::send"); + return ACE_OS::write (this->get_handle (), + (const char *) buf, n, + overlapped); +} + +inline ssize_t +ACE_FILE_IO::recv (void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_FILE_IO::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n, + overlapped); +} +#endif /* ACE_HAS_STREAM_PIPES */ diff --git a/ace/Future.cpp b/ace/Future.cpp new file mode 100644 index 00000000000..3114afaf637 --- /dev/null +++ b/ace/Future.cpp @@ -0,0 +1,346 @@ +// Future.cpp +// $Id$ + +#define ACE_BUILD_DLL + +#if !defined (ACE_FUTURE_CPP) +#define ACE_FUTURE_CPP + +#include "ace/Future.h" + +#if defined (ACE_HAS_THREADS) + +// Dump the state of an object. + +template <class T> void +ACE_Future_Rep<T>::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, + "ref_count_ = %d\n", + this->ref_count_)); + ACE_DEBUG ((LM_INFO,"value_: \n")); + if (this->value_) + ACE_DEBUG ((LM_DEBUG," (NON-NULL)\n")); + else + ACE_DEBUG ((LM_DEBUG," (NULL)\n")); + ACE_DEBUG ((LM_INFO,"value_ready_: \n")); + this->value_ready_.dump (); + ACE_DEBUG ((LM_INFO,"value_ready_mutex_: \n")); + this->value_ready_mutex_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class T> +ACE_Future_Rep<T>::ACE_Future_Rep (void) + : ref_count_ (0), + value_ (0), + value_ready_ (this->value_ready_mutex_) +{ +} + +template <class T> +ACE_Future_Rep<T>::~ACE_Future_Rep (void) +{ + delete this->value_; + this->value_ = 0; +} + +template <class T> int +ACE_Future_Rep<T>::ready (void) +{ + return this->value_ != 0; +} + +template <class T> int +ACE_Future_Rep<T>::set (const T &r) +{ + // If the value is already produced, ignore it... + if (this->value_ == 0) + { + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->value_ready_mutex_, -1)); + // Otherwise, create a new result value. Note the use of the + // Double-checked locking pattern to avoid multiple allocations. + + if (this->value_ == 0) + ACE_NEW_RETURN (this->value_, T (r), -1); + + // Signal all the waiting threads. + return this->value_ready_.broadcast (); + + // Destructor releases the lock. + } + return 0; +} + +template <class T> int +ACE_Future_Rep<T>::get (T &value, ACE_Time_Value *tv) +{ + // If the value is already produced, return it. + if (this->value_ == 0) + { + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->value_ready_mutex_, -1)); + + // If the value is not yet defined we must block until the + // producer writes to it. + + while (this->value_ == 0) + { + // Perform a timed wait. + if (this->value_ready_.wait (tv) == -1) + return -1; + } + // Destructor releases the lock. + } + + value = *this->value_; + return 0; +} + +template <class T> +ACE_Future_Rep<T>::operator T () +{ + // If the value is already produced, return it. + if (this->value_ == 0) + { + // constructor of ace_mon acquires the mutex + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->value_ready_mutex_, 0)); + + // If the value is not yet defined we must block until the + // producer writes to it. + + while (this->value_ == 0) + { + // wait forever + if (this->value_ready_.wait () == -1) + return 0; + } + + // Destructor releases the mutex + + } + + return *this->value_; +} + + +template <class T> +ACE_Future<T>::ACE_Future (void) + : future_rep_ (0) +{ +} + +template <class T> +ACE_Future<T>::ACE_Future (const ACE_Future<T> &r) +{ + + // copy constructor: + // + // bind <this> to the same <ACE_Future_Rep> as <r>. + + // @@ not really clear if this is needed... after all this + // ACE_Future is just being instantiated... + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); + + // acquire the mutex on <r>. We have to make sure + // that <r> does not delete its future_rep_... + + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, (ACE_Thread_Mutex &) r.mutex_)); + + // Check if 'r' has already a ACE_Future_rep bound to it. + if (r.future_rep_ == 0) + this->future_rep_ = r.create_rep_i (); + else + // ACE_Future_rep exists already, we can just link to it. + this->future_rep_ = r.future_rep_; + + this->future_rep_->ref_count_++; + +} + +template <class T> +ACE_Future<T>::ACE_Future (const T &r) +{ + ACE_DEBUG ((LM_DEBUG," (%t) funny constructor\n")); + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); + this->create_rep_i ()->set (r); +} + +template <class T> +ACE_Future<T>::~ACE_Future (void) +{ + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); + + if (this->future_rep_) + { + this->future_rep_->ref_count_--; + + if (this->future_rep_->ref_count_ == 0) + { + delete this->future_rep_; + this->future_rep_ = 0; + } + } + +} + +template <class T> int +ACE_Future<T>::operator== (const ACE_Future<T> &r) const +{ + return r.future_rep_ == this->future_rep_; +} + +template <class T> int +ACE_Future<T>::operator!= (const ACE_Future<T> &r) const +{ + return r.future_rep_ != this->future_rep_; +} + +template <class T> int +ACE_Future<T>::cancel (const T &r) +{ + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1)); + + // If this ACE_Future is already attached to a ACE_Future_Rep, + // detach it (maybe delete the ACE_Future_Rep). + if (this->future_rep_) + { + this->future_rep_->ref_count_--; + + if (this->future_rep_->ref_count_ == 0) + delete this->future_rep_; + } + + // Make a new ACE_Future_Rep and immediately assign + // the new value to it. + this->create_rep_i (); + return this->future_rep_->set (r); +} + +template <class T> int +ACE_Future<T>::set (const T &r) +{ + if (this->future_rep_) + // Give the pointer to the result to the ACE_Future_Rep. + return this->future_rep_->set (r); + else + // @@ Maybe this should return a special value to indicate that + // there's no <ACE_Future_Rep> yet? + return 0; +} + +template <class T> ACE_Future_Rep<T> * +ACE_Future<T>::create_rep_i (void) const +{ + // Should only be called internally with locks held. + ACE_NEW_RETURN (((ACE_Future<T> *) this)->future_rep_, ACE_Future_Rep<T>, 0); + this->future_rep_->ref_count_ = 1; + return this->future_rep_; +} + +template <class T> int +ACE_Future<T>::ready (void) +{ + // We're ready if the ACE_Future_rep is ready... + if (this->future_rep_) + return this->future_rep_->ready (); + else + return 0; +} + +template <class T> int +ACE_Future<T>::get (T &value, ACE_Time_Value *tv) +{ + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1)); + + if (this->future_rep_ == 0) + // Oops, we have to create a ACE_Future_Rep first. + this->create_rep_i (); + + // We return the ACE_Future_rep. + return this->future_rep_->get (value, tv); +} + +template <class T> +ACE_Future<T>::operator T () +{ + // note that this will fail (and COREDUMP!) + // if future_rep_ == 0 ! + // + // but... + // this is impossible unless somebody is so stupid to + // try something like this: + // + // Future<T> futT; + // T t; + // t = futT; + + // perform type conversion on Future_Rep. + return *future_rep_; +} + +template <class T> void +ACE_Future<T>::operator = (const ACE_Future<T> &r) +{ + // assignment: + // + // bind <this> to the same <ACE_Future_Rep> as <r>. + + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); + + // if there is already a <ACE_Future_Rep> we have + // to disconnect from it... + if (this->future_rep_) + { + // Disconnect from the <ACE_Future_Rep>. + this->future_rep_->ref_count_--; + + if (this->future_rep_->ref_count_ == 0) + delete this->future_rep_; + } + + // Acquire the mutex on <r>. We have to make sure + // that <r> does not delete it's future_rep_... + + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, (ACE_Thread_Mutex &) r.mutex_)); + + // Check if 'r' has already a ACE_Future_rep bound to it. + if (r.future_rep_ == 0) + this->future_rep_ = r.create_rep_i (); + else + // ACE_Future_rep exists already, we can just link to it. + this->future_rep_ = r.future_rep_; + + this->future_rep_->ref_count_++; +} + +template <class T> void +ACE_Future<T>::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + if (this->future_rep_) + this->future_rep_->dump (); + + this->mutex_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class T> void * +ACE_Future<T>::operator new (size_t nbytes) +{ + return 0; +} + +template <class T> void +ACE_Future<T>::operator delete (void *) +{ +} + +template <class T> void +ACE_Future<T>::operator &() +{ +} + +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_FUTURE_CPP */ diff --git a/ace/Future.h b/ace/Future.h new file mode 100644 index 00000000000..1d0a13e057d --- /dev/null +++ b/ace/Future.h @@ -0,0 +1,167 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Future.h +// +// = AUTHOR +// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt +// <schmidt@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_FUTURE_H) +#define ACE_FUTURE_H + +#include "ace/Synch.h" + +#if defined (ACE_HAS_THREADS) + +// Forward decl. +template <class T> class ACE_Future; + +template <class T> class ACE_Future_Rep +// = TITLE +// +// ACE_Future_Rep<T> +// +// = DESCRIPTION +// An ACE_Future_Rep<T> object encapsules a pointer to an +// object of class T which is the result of an asynchronous +// method invocation. It is pointed to by ACE_Future<T> object[s] +// and only accessible through them. +{ + friend class ACE_Future<T>; + +private: + + int set (const T &r); + // Set the result value. + + int get (T &value, ACE_Time_Value *tv); + // Wait up to <tv> time to get the <value>. + + operator T(); + // Type conversion. will block forever until the + // result is available. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + // = constructor and destructor private + ACE_Future_Rep (void); + ~ACE_Future_Rep (void); + + int ready (void); + // Is result available? + + T *value_; + // Pointer to the result. + + ACE_Atomic_Op<ACE_Thread_Mutex, int> ref_count_; + // Reference count. + + // = Condition variable and mutex that protect the <value_>. + ACE_Condition_Thread_Mutex value_ready_; + ACE_Thread_Mutex value_ready_mutex_; +}; + +template <class T> class ACE_Future + // = TITLE + // This class implements a ``single write, multiple read'' pattern + // that can be used to return results from asynchronous method + // invocations. + // = DESCRIPTION +{ +public: + // = Initialization and termination methods. + ACE_Future (void); + // Constructor. + + ACE_Future (const ACE_Future<T> &r); + // Copy constructor binds <this> and <r> to the same + // <ACE_Future_Rep>. An <ACE_Future_Rep> is created if necessary. + + ACE_Future (const T &r); + // Constructor that initialises an <ACE_Future> to point to the + // result <r> immediately. + + ~ACE_Future (void); + // Destructor. + + void operator = (const ACE_Future<T> &r); + // Assignment operator that binds <this> and <r> to the same + // <ACE_Future_Rep>. An <ACE_Future_Rep> is created if necessary. + + int cancel (const T &r); + // Cancel an <ACE_Future> and assign the value <r>. It is used if a + // client does not want to wait for <T> to be produced. + + int operator == (const ACE_Future<T> &r) const; + // Equality operator that returns 1 if both ACE_Future<T> objects + // point to the same ACE_Future_Rep<T> object. Attention: It also + // returns 1 if both objects have just been instantiated and not + // used yet. + + int operator != (const ACE_Future<T> &r) const; + // Inequality operator, which is the opposite of equality. + + int set (const T &r); + // Make the result available. Is used by the server thread to give + // the result to all waiting clients. + + int get (T &value, ACE_Time_Value *tv = 0); + // Wait up to <tv> time to get the <value>. + + operator T (); + // type conversion. obtain the result of the asynchronous method + // invocation. will block forever. + + int ready (void); + // Check if the result is available. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Future_Rep<T> *create_rep_i (void) const; + // Create the <ACE_Future_Rep> object. + + void* operator new (size_t nbytes); + // Do not allow new operator. + + void operator delete(void *); + // Do not allow delete operator + + void operator &(); + // Do not allow address-of operator. + + ACE_Future_Rep<T> *future_rep_; + // the ACE_Future_Rep + + ACE_Thread_Mutex mutex_; + // Protect operations on the <Future>. + +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Future.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Future.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_FUTURE_H */ diff --git a/ace/Get_Opt.cpp b/ace/Get_Opt.cpp new file mode 100644 index 00000000000..5279d4c6912 --- /dev/null +++ b/ace/Get_Opt.cpp @@ -0,0 +1,133 @@ +// Get_Opt.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Get_Opt.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Get_Opt.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Get_Opt) + +void +ACE_Get_Opt::dump (void) const +{ + ACE_TRACE ("ACE_Get_Opt::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_Get_Opt::operator () (void) +{ + ACE_TRACE ("ACE_Get_Opt::operator"); + if (this->nextchar == 0 || *this->nextchar == 0) + { + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (this->optind != this->nargc && !::strcmp (this->nargv[this->optind], "--")) + { + this->optind++; + + if (this->first_nonopt == this->last_nonopt) + this->first_nonopt = this->optind; + this->last_nonopt = this->nargc; + + this->optind = this->nargc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (this->optind == this->nargc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (this->first_nonopt != this->last_nonopt) + this->optind = this->first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (this->nargv[this->optind][0] != '-' || this->nargv[this->optind][1] == 0) + return EOF; + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + this->nextchar = this->nargv[this->optind] + 1; + } + + /* Look at and handle the next option-character. */ + + { + char c = *this->nextchar++; + char *temp = (char *) strchr (this->noptstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*this->nextchar == 0) + this->optind++; + + if (temp == 0 || c == ':') + { + if (this->opterr != 0) + { + if (c < 040 || c >= 0177) + ACE_ERROR ((LM_ERROR, "%s: unrecognized option, character code 0%o\n", + this->nargv[0], c)); + else + ACE_ERROR ((LM_ERROR, "%s: unrecognized option `-%c'\n", + this->nargv[0], c)); + } + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*this->nextchar != 0) + { + this->optarg = this->nextchar; + this->optind++; + } + else + this->optarg = 0; + this->nextchar = 0; + } + else + { + /* This is an option that requires an argument. */ + if (*this->nextchar != 0) + { + this->optarg = this->nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + this->optind++; + } + else if (this->optind == this->nargc) + { + if (this->opterr != 0) + ACE_ERROR ((LM_ERROR, "%s: no argument for `-%c' option\n", + this->nargv[0], c)); + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + this->optarg = this->nargv[this->optind++]; + this->nextchar = 0; + } + } + return c; + } +} diff --git a/ace/Get_Opt.h b/ace/Get_Opt.h new file mode 100644 index 00000000000..0e26a51e807 --- /dev/null +++ b/ace/Get_Opt.h @@ -0,0 +1,161 @@ +/* -*- C++ -*- */ +// $Id$ + +/* ACE_Get_Opt for GNU. + Copyright (C) 1987, 1989 Free Software Foundation, Inc. (Modified + by Douglas C. Schmidt for use with C++.) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 1, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Get_Opt.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_GET_OPT_H) +#define ACE_GET_OPT_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Get_Opt + // = TITLE + // Iterator for parsing command-line arguments. + // + // = DESCRIPTION + // This version of `get_opt' appears to the caller like standard + // Unix `get_opt' but it behaves differently for the user, since it + // allows the user to intersperse the options with the other + // arguments. + // + // As `get_opt' works, it permutes the elements of `argv' so that, + // when it is done, all the options precede everything else. Thus + // all application programs are extended to handle flexible argument order. + // + // Setting the environment variable _POSIX_OPTION_ORDER disables permutation. + // Then the behavior is completely standard. + // + // GNU application programs can use a third alternative mode in which + // they can distinguish the relative order of options and other arguments. + +{ +public: + ACE_Get_Opt (int argc, char **argv, char *optstring, int skip_argv0 = 1, int report_errors = 0); + // Initialize the internal data when the first call is made. Start + // processing options with ARGV-element 0 + <skip_argv0>; the + // sequence of previously skipped non-option ARGV-elements is empty. + + int operator () (void); + // Scan elements of ARGV (whose length is ARGC) for option + // characters given in OPTSTRING. + // + // If an element of ARGV starts with '-', and is not exactly "-" or "--", + // then it is an option element. The characters of this element + // (aside from the initial '-') are option characters. If `get_opt' + // is called repeatedly, it returns successively each of the option characters + // from each of the option elements. + // + // If `get_opt' finds another option character, it returns that character, + // updating `optind' and `nextchar' so that the next call to `get_opt' can + // resume the scan with the following option character or ARGV-element. + // + // If there are no more option characters, `get_opt' returns `EOF'. + // Then `optind' is the index in ARGV of the first ARGV-element + // that is not an option. (The ARGV-elements have been permuted + // so that those that are not options now come last.) + // + // OPTSTRING is a string containing the legitimate option characters. + // A colon in OPTSTRING means that the previous character is an option + // that wants an argument. The argument is taken from the rest of the + // current ARGV-element, or from the following ARGV-element, + // and returned in `optarg'. + // + // If an option character is seen that is not listed in OPTSTRING, + // return '?' after printing an error message. If you set `opterr' to + // zero, the error message is suppressed but we still return '?'. + // + // If a char in OPTSTRING is followed by a colon, that means it wants an arg, + // so the following text in the same ARGV-element, or the text of the following + // ARGV-element, is returned in `optarg. Two colons mean an option that + // wants an optional arg; if there is text in the current ARGV-element, + // it is returned in `optarg'. + // + // If OPTSTRING starts with `-', it requests a different method of handling the + // non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */ + + // = Public data members (should be hidden...). + + char *optarg; + // For communication from `get_opt' to the caller. When `get_opt' + // finds an option that takes an argument, the argument value is + // returned here. Also, when `ordering' is RETURN_IN_ORDER, each + // non-option ARGV-element is returned here. + + int optind; + // Index in ARGV of the next element to be scanned. This is used + // for communication to and from the caller and for communication + // between successive calls to `get_opt'. On entry to `get_opt', + // zero means this is the first call; initialize. + // + // When `get_opt' returns EOF, this is the index of the first of the + // non-option elements that the caller should itself scan. + // + // Otherwise, `optind' communicates from one call to the next + // how much of ARGV has been scanned so far. + + int opterr; + // Callers store zero here to inhibit the error message for + // unrecognized options. + + // = GNU extensions + int nargc; + char **nargv; + char *noptstring; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + + char *nextchar; + // The next char to be scanned in the option-element in which the + // last option character we returned was found. This allows us to + // pick up the scan where we left off. + // + // If this is zero, or a null string, it means resume the scan + // by advancing to the next ARGV-element. + + int first_nonopt; + int last_nonopt; + // Describe the part of ARGV that contains non-options that have + // been skipped. `first_nonopt' is the index in ARGV of the first + // of them; `last_nonopt' is the index after the last of them. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Get_Opt.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_GET_OPT_H */ diff --git a/ace/Get_Opt.i b/ace/Get_Opt.i new file mode 100644 index 00000000000..9481fc30145 --- /dev/null +++ b/ace/Get_Opt.i @@ -0,0 +1,23 @@ +/* -*- C++ -*- */ +// $Id$ + +// Get_Opt.i + +ACE_INLINE +ACE_Get_Opt::ACE_Get_Opt (int argc, + char **argv, + char *optstring, + int skip, + int report_errors) + : opterr (report_errors), + nextchar (0), + optarg (0), + first_nonopt (skip), + last_nonopt (skip), + optind (skip), + noptstring (optstring), + nargc (argc), + nargv (argv) +{ + ACE_TRACE ("ACE_Get_Opt::ACE_Get_Opt"); +} diff --git a/ace/Handle_Set.cpp b/ace/Handle_Set.cpp new file mode 100644 index 00000000000..d20f114cb05 --- /dev/null +++ b/ace/Handle_Set.cpp @@ -0,0 +1,213 @@ +// Handle_Set.cpp +// $Id$ + +/* Wrapper for the ACE_HANDLE set abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Handle_Set.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Handle_Set.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set) + +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_DEBUG ((LM_DEBUG, "size_ = %d", this->size_)); + ACE_DEBUG ((LM_DEBUG, "\nmax_handle_ = %d", this->max_handle_)); + +#if defined(ACE_WIN32) + for (size_t i = 0; i < this->mask_.fd_count + 1; i++) + ACE_DEBUG ((LM_DEBUG, " %x ", this->mask_.fd_array[i])); +#else /* !ACE_WIN32 */ + for (size_t i = 0; i < this->max_handle_ + 1; i++) + if (this->is_set (i)) + ACE_DEBUG ((LM_DEBUG, " %d ", i)); +#endif /* ACE_WIN32 */ + + ACE_DEBUG ((LM_DEBUG, " ]")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_HAS_BROKEN_BITSHIFT) +static const ACE_UINT32 MSB_MASK = ~(ACE_UINT32 (1) << ACE_UINT32 (NFDBITS - 1)); +#else +// This needs to go here to avoid overflow problems on some compilers. +static const ACE_UINT32 MSB_MASK = ~(1 << (NFDBITS - 1)); +#endif /* ACE_HAS_BROKEN_BITSHIFT */ + +// Table that maps bytes to counts of the enabled bits. + +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); +#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 (unsigned long n) const +{ + ACE_TRACE ("ACE_Handle_Set::count_bits"); + 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]); +} + +// Synchronize the underlying FD_SET with the MAX_FD and the SIZE. + +void +ACE_Handle_Set::sync (ACE_HANDLE max) +{ + ACE_TRACE ("ACE_Handle_Set::sync"); +#if !defined(ACE_WIN32) + this->size_ = 0; + + for (int i = (max - 1) / ACE_Handle_Set::WORDSIZE; i >= 0; i--) + this->size_ += count_bits (this->mask_.fds_bits[i]); + + this->set_max (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) + if (this->size_ == 0) + this->max_handle_ = -1; + else + { + int i; + + for (i = (current_max - 1) / ACE_Handle_Set::WORDSIZE; + this->mask_.fds_bits[i] == 0; + i--) + continue; + + this->max_handle_ = i * ACE_Handle_Set::WORDSIZE; + for (fd_mask val = this->mask_.fds_bits[i]; + (val & ~1) != 0; + val = (val >> 1) & MSB_MASK) + this->max_handle_++; + } + + // Do some sanity checking... + if (this->max_handle_ >= ACE_Handle_Set::MAXSIZE) + this->max_handle_ = ACE_Handle_Set::MAXSIZE - 1; +#endif /* !ACE_WIN32 */ +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set_Iterator) + +void +ACE_Handle_Set_Iterator::dump (void) const +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "num_ = %d", this->num_)); + ACE_DEBUG ((LM_DEBUG, "\nindex_ = %d", this->index_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Handle_Set_Iterator::operator++ (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::operator++"); + +#if defined(ACE_WIN32) + this->index_++; +#else /* !ACE_WIN32 */ + this->val_ = (this->val_ >> 1) & MSB_MASK; + this->num_++; + + + if (this->val_ == 0) + { + for (this->index_++; + this->index_ < ACE_Handle_Set::NUM_WORDS + && this->handles_.mask_.fds_bits[this->index_] == 0; + this->index_++) + continue; + + if (this->index_ >= ACE_Handle_Set::NUM_WORDS) + { + this->num_ = this->handles_.max_handle_ + 1; + return; + } + else + { + this->val_ = this->handles_.mask_.fds_bits[this->index_]; + this->num_ = this->index_ * ACE_Handle_Set::WORDSIZE; + } + } + + for (; ACE_BIT_DISABLED (this->val_, 1); this->num_++) + this->val_ = (this->val_ >> 1) & MSB_MASK; +#endif /* !ACE_WIN32 */ +} + +ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator (const ACE_Handle_Set &f) + : handles_ (f), + index_ (0), + num_ (0) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator"); +#if !defined(ACE_WIN32) + for (; + this->handles_.mask_.fds_bits[this->index_] == 0; + this->index_++) + this->num_ += ACE_Handle_Set::WORDSIZE; + + for (this->val_ = this->handles_.mask_.fds_bits[this->index_]; + (ACE_BIT_DISABLED (this->val_, 1)) && this->num_ < ACE_Handle_Set::MAXSIZE; + this->num_++) + this->val_ = (this->val_ >> 1) & MSB_MASK; +#endif /* !ACE_WIN32 */ +} diff --git a/ace/Handle_Set.h b/ace/Handle_Set.h new file mode 100644 index 00000000000..8789ddde300 --- /dev/null +++ b/ace/Handle_Set.h @@ -0,0 +1,153 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Handle_Set.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_HANDLE_SET_H) +#define ACE_HANDLE_SET_H + +#include "ace/ACE.h" + +// This wrapper design is not very portable to DEC OSF/1 I had to +// redefine NFDBITS to 32. On OSF/1 NFDBITS is a macro that expands to +// (sizeof(fd_mask)*8) which is 4096 by default. This was an +// inappropriate value for defining the MSB_MASK default value. Any +// ideas? The workaround is a pretty severe restriction for OSF/1. +// DJT +// #if defined (__osf__) +// #define NFDBITS 32 +// #endif + +class ACE_Export ACE_Handle_Set +{ + // = TITLE + // C++ wrapper for the socket <FD_SET> abstraction. +friend class ACE_Handle_Set_Iterator; +public: + // = Initialization and termination. + + enum + { + MAXSIZE = ACE_DEFAULT_REACTOR_SIZE + }; + + // = Initialization methods. + ACE_Handle_Set (void); + // Constructor, initializes the bitmask to all 0s. + + ACE_Handle_Set (const ACE_FD_SET_TYPE &mask); + + // = Methods for manipulating bitsets. + void reset (void); + // Initialize the bitmask to all 0s and reset the associated fields. + + int is_set (ACE_HANDLE) const; + // Checks whether handle is enabled. + + void set_bit (ACE_HANDLE); + // Enables the handle. + + void clr_bit (ACE_HANDLE); + // Disables the handle. + + int num_set (void) const; + // Returns a count of the number of enabled bits. + + ACE_HANDLE max_set (void) const; + // Returns the number of the large bit. + + void sync (ACE_HANDLE max); + // Synchronize the underlying FD_SET with the MAX_FD and the SIZE. + + operator fd_set *(); + // Returns a pointer to the underlying fd_set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int size_; + // Size of the set. + + ACE_HANDLE max_handle_; + // Current max handle. + + fd_set mask_; + // Bitmask. + + enum + { + WORDSIZE = NFDBITS, +#if !defined(ACE_WIN32) + NUM_WORDS = howmany (MAXSIZE, NFDBITS), +#endif + NBITS = 256 + }; + + int count_bits (unsigned long n) const; + // Counts the number of bits enabled in N. Uses a table lookup to + // speed up the count. + + void set_max (ACE_HANDLE max); + // Resets the MAX_FD after a clear of the original MAX_FD. + + static const char nbits_[ACE_Handle_Set::NBITS]; + // Table that maps bytes to counts of the enabled bits. +}; + +class ACE_Export ACE_Handle_Set_Iterator + // = TITLE + // Iterator for the ACE_Handle_Set abstraction. +{ +public: + ACE_Handle_Set_Iterator (const ACE_Handle_Set &); + // Constructor. + + ACE_HANDLE operator ()(void); + // "Next" operator. + + void operator++ (void); + // Advance by "one." + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const ACE_Handle_Set &handles_; + // The <Handle_Set> we are iterating through. + + int num_; + // Number of the word we're iterating on. + + size_t index_; + // Index of the current <num_> word. + +#if !defined (ACE_WIN32) + fd_mask val_; +#endif /* ACE_WIN32 */ + // Value of the bits in the word we're iterating on. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Handle_Set.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HANDLE_SET */ diff --git a/ace/Handle_Set.i b/ace/Handle_Set.i new file mode 100644 index 00000000000..d7577404ea3 --- /dev/null +++ b/ace/Handle_Set.i @@ -0,0 +1,107 @@ +/* -*- C++ -*- */ +// $Id$ + +// Handle_Set.i + +// Initialize the bitmask to all 0s and reset the associated fields. + +ACE_INLINE void +ACE_Handle_Set::reset (void) +{ + ACE_TRACE ("ACE_Handle_Set::reset"); + this->max_handle_ = ACE_INVALID_HANDLE; + this->size_ = 0; + FD_ZERO (&this->mask_); +} + +// 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"); + return FD_ISSET (handle, &this->mask_); +} + +// Enables the handle. + +ACE_INLINE void +ACE_Handle_Set::set_bit (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Handle_Set::set_bit"); + if (!this->is_set (handle)) + { +#if defined(ACE_WIN32) + FD_SET ((SOCKET)handle, &this->mask_); +#else /* !ACE_WIN32 */ + 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 (this->is_set (handle)) + { +#if defined(ACE_WIN32) + FD_CLR ((SOCKET)handle, &this->mask_); +#else /* !ACE_WIN32 */ + FD_CLR (handle, &this->mask_); + this->size_--; + + 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 ACE_FD_SET_TYPE *"); + return (fd_set *) &this->mask_; +} + +ACE_INLINE ACE_HANDLE +ACE_Handle_Set_Iterator::operator () (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::operator"); +#if defined(ACE_WIN32) + return this->index_ < this->handles_.mask_.fd_count + ? (ACE_HANDLE)this->handles_.mask_.fd_array[this->index_] + : ACE_INVALID_HANDLE; +#else /* !ACE_WIN32 */ + return this->num_ <= this->handles_.max_handle_ ? this->num_ : -1; +#endif /* ACE_WIN32 */ +} diff --git a/ace/High_Res_Timer.cpp b/ace/High_Res_Timer.cpp new file mode 100644 index 00000000000..aad19e26799 --- /dev/null +++ b/ace/High_Res_Timer.cpp @@ -0,0 +1,74 @@ +// High_Res_Timer.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/High_Res_Timer.h" + +#if !defined (__ACE_INLINE__) +#include "ace/High_Res_Timer.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_HAS_HI_RES_TIMER) + +ACE_ALLOC_HOOK_DEFINE(ACE_High_Res_Timer) + +void +ACE_High_Res_Timer::dump (void) const +{ + ACE_TRACE ("ACE_High_Res_Timer::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_High_Res_Timer::reset (void) +{ + ACE_TRACE ("ACE_High_Res_Timer::reset"); + (void) ACE_OS::memset (&this->start_, 0, sizeof this->start_); + (void) ACE_OS::memset (&this->end_, 0, sizeof this->end_); + (void) ACE_OS::memset (&this->total_, 0, sizeof this->total_); + (void) ACE_OS::memset (&this->temp_, 0, sizeof this->temp_); +} + +ACE_High_Res_Timer::ACE_High_Res_Timer (void) +{ + ACE_TRACE ("ACE_High_Res_Timer::ACE_High_Res_Timer"); + this->reset (); +} + +void +ACE_High_Res_Timer::print_ave (char *str, int count, ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_High_Res_Timer::print_ave"); +#if defined (ACE_HAS_LONGLONG_T) + hrtime_t total = this->end_ - this->start_; + hrtime_t avg_nsecs = total / count; + hrtime_t total_secs = total / (1000 * 1000 * 1000); + hrtime_t extra_nsecs = total - (total_secs * (1000 * 1000 * 1000)); + char buf[100]; + + ACE_OS::sprintf (buf, "%s count = %d, total (secs %lld, usecs %lld), avg usecs = %lld\n", + str, count, total_secs, extra_nsecs / 1000, avg_nsecs / 1000); + ACE_OS::write (handle, buf, strlen (buf)); +#endif /* ACE_HAS_LONGLONG_T */ +} + +void +ACE_High_Res_Timer::print_total (char *str, int count, ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_High_Res_Timer::print_total"); +#if defined (ACE_HAS_LONGLONG_T) + hrtime_t avg_nsecs = this->total_ / count; + hrtime_t total_secs = this->total_ / (1000 * 1000 * 1000); + hrtime_t extra_nsecs = this->total_ - (total_secs * (1000 * 1000 * 1000)); + char buf[100]; + + ACE_OS::sprintf (buf, "%s count = %d, total (secs %lld, usecs %lld), avg usecs = %lld\n", + str, count, total_secs, extra_nsecs / 1000, avg_nsecs / 1000); + ACE_OS::write (handle, buf, strlen (buf)); +#endif /* ACE_HAS_LONGLONG_T */ +} +#endif /* ACE_HAS_HI_RES_TIMER */ diff --git a/ace/High_Res_Timer.h b/ace/High_Res_Timer.h new file mode 100644 index 00000000000..76ac9409fff --- /dev/null +++ b/ace/High_Res_Timer.h @@ -0,0 +1,86 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// High_Res_Timer.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_HIGH_RES_TIMER_H) +#define ACE_HIGH_RES_TIMER_H + +#include "ace/ACE.h" + +#if defined (ACE_HAS_HI_RES_TIMER) + +class ACE_Export ACE_High_Res_Timer + // = TITLE + // A high resolution timer class wrapper that encapsulates + // Solaris timers. +{ +public: + // = Initialization method. + + ACE_High_Res_Timer (void); + // Initialize the timer. + + void reset (void); + // Reinitialize the timer. + + void start (void); + // Start timing. + + void stop (void); + // Stop timing. + + void start_incr (void); + // Start incremental timing. + + void stop_incr (void); + // Stop incremental timing. + + void print_total (char *message, + int iterations, + ACE_HANDLE handle); + // Print total time. + + void print_ave (char *message, + int iterations, + ACE_HANDLE handle); + // Print average time. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + hrtime_t start_; + // Starting time. + + hrtime_t end_; + // Ending time. + + hrtime_t total_; + // Total elapsed time. + + hrtime_t temp_; + // Temp time used for incremental timing. +}; + +#if defined (__ACE_INLINE__) +#include "ace/High_Res_Timer.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_HI_RES_TIMER */ +#endif /* ACE_HIGH_RES_TIMER_H */ diff --git a/ace/High_Res_Timer.i b/ace/High_Res_Timer.i new file mode 100644 index 00000000000..c33a1ded0c4 --- /dev/null +++ b/ace/High_Res_Timer.i @@ -0,0 +1,37 @@ +/* -*- C++ -*- */ +// $Id$ + +// High_Res_Timer.i + +#if defined (ACE_HAS_HI_RES_TIMER) + +ACE_INLINE void +ACE_High_Res_Timer::start (void) +{ + ACE_TRACE ("ACE_High_Res_Timer::start"); + this->start_ = ACE_OS::gethrtime (); +} + +ACE_INLINE void +ACE_High_Res_Timer::stop (void) +{ + ACE_TRACE ("ACE_High_Res_Timer::stop"); + this->end_ = ACE_OS::gethrtime (); +} + +ACE_INLINE void +ACE_High_Res_Timer::start_incr (void) +{ + ACE_TRACE ("ACE_High_Res_Timer::start_incr"); + this->temp_ = ACE_OS::gethrtime (); +} + +ACE_INLINE void +ACE_High_Res_Timer::stop_incr (void) +{ + ACE_TRACE ("ACE_High_Res_Timer::stop_incr"); +#if defined (ACE_HAS_LONGLONG_T) + this->total_ += (ACE_OS::gethrtime () - this->temp_); +#endif /* ACE_HAS_LONGLONG_T */ +} +#endif /* ACE_HAS_HI_RES_TIMER */ diff --git a/ace/INET_Addr.cpp b/ace/INET_Addr.cpp new file mode 100644 index 00000000000..1f131f1b7f2 --- /dev/null +++ b/ace/INET_Addr.cpp @@ -0,0 +1,413 @@ +// INET_Addr.cpp +// $Id$ + +/* Defines the Internet domain address family address format. */ + +#define ACE_BUILD_DLL +#include "ace/INET_Addr.h" + +#if !defined (__ACE_INLINE__) +#include "ace/INET_Addr.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_INET_Addr) + +void +ACE_INET_Addr::dump (void) const +{ + ACE_TRACE ("ACE_INET_Addr::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + char s[MAXNAMELEN]; + ACE_OS::sprintf (s, "%s:%d", this->get_host_addr (), this->get_port_number ()); + ACE_DEBUG ((LM_DEBUG, "%s", s)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Compare two addresses for inequality. + +int +ACE_INET_Addr::operator != (const ACE_Addr &sap) const +{ + ACE_TRACE ("ACE_INET_Addr::operator !="); + return !((*this) == sap); +} + +// Compare two addresses for equality. + +int +ACE_INET_Addr::operator == (const ACE_Addr &sap) const +{ + ACE_TRACE ("ACE_INET_Addr::operator =="); + const sockaddr_in &inet_sap = ((const ACE_INET_Addr &) sap).inet_addr_; + + return this->inet_addr_.sin_port == inet_sap.sin_port + && ACE_OS::memcmp ((void *) &this->inet_addr_.sin_addr, + (void *) &inet_sap.sin_addr, + sizeof (this->inet_addr_.sin_addr)) == 0; +} + +ACE_INET_Addr::ACE_INET_Addr (void) + : ACE_Addr (AF_INET, sizeof this->inet_addr_) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + (void) ACE_OS::memset ((void *) &this->inet_addr_, 0, + sizeof this->inet_addr_); +} + +int +ACE_INET_Addr::set (const ACE_INET_Addr &sa) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + this->ACE_Addr::base_set (AF_INET, sizeof this->inet_addr_); + (void) ACE_OS::memcpy ((void *) &this->inet_addr_, + (void *) &sa.inet_addr_, + sizeof this->inet_addr_); + return 0; +} + +// Transform the string into the current addressing format. + +ACE_INLINE int +ACE_INET_Addr::string_to_addr (const char s[]) +{ + ACE_TRACE ("ACE_INET_Addr::string_to_addr"); + // Need to make a duplicate since we'll be overwriting the string. + char *t = ACE_OS::strdup (s); + if (t == 0) + return -1; + + char *ip_addr = ACE_OS::strchr (t, ':'); + int result; + + if (ip_addr == 0) // Assume it's a port number. + { + u_short port = ACE_OS::atoi (t); + result = this->set (port, ACE_UINT32 (INADDR_ANY)); + } + else + { + *ip_addr = '\0'; + u_short port = ACE_OS::atoi (ip_addr + 1); // Skip over ':' + result = this->set (port, t); + } + ACE_OS::free (ACE_MALLOC_T (t)); + return result; +} + +int +ACE_INET_Addr::set (const char address[]) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + return this->string_to_addr (address); +} + +ACE_INET_Addr::ACE_INET_Addr (const char address[]) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + this->set (address); +} + +// Copy constructor. + +ACE_INET_Addr::ACE_INET_Addr (const ACE_INET_Addr &sa) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + this->set (sa); +} + +// Initializes a ACE_INET_Addr from a PORT_NUMBER and an Internet +// address. + +int +ACE_INET_Addr::set (u_short port_number, + ACE_UINT32 inet_address, + int encode) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + this->ACE_Addr::base_set (AF_INET, sizeof this->inet_addr_); + (void) ACE_OS::memset ((void *) &this->inet_addr_, + 0, sizeof this->inet_addr_); + this->inet_addr_.sin_family = AF_INET; +#if defined (ACE_HAS_SIN_LEN) + this->inet_addr_.sin_len = sizeof this->inet_addr_; +#endif /* ACE_HAS_SIN_LEN */ + + if (encode) + { + inet_address = htonl (inet_address); + this->inet_addr_.sin_port = htons (port_number); + } + else + this->inet_addr_.sin_port = port_number; + + (void) ACE_OS::memcpy ((void *) &this->inet_addr_.sin_addr, + (void *) &inet_address, + sizeof this->inet_addr_.sin_addr); + return 0; +} + +// Initializes a ACE_INET_Addr from a PORT_NUMBER and the remote +// HOST_NAME. + +int +ACE_INET_Addr::set (u_short port_number, + const char host_name[], + int encode) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + ACE_UINT32 addr; + + this->ACE_Addr::base_set (AF_INET, sizeof this->inet_addr_); + (void) ACE_OS::memset ((void *) &this->inet_addr_, 0, sizeof + this->inet_addr_); + + // Yow, someone gave us a NULL host_name! + if (host_name == 0) + { + errno = EINVAL; + return -1; + } + else if ((addr = ACE_OS::inet_addr (host_name)) != (ACE_UINT32) -1 + // Broadcast addresses are weird... + || ACE_OS::strcmp (host_name, "255.255.255.255") == 0) + return this->set (port_number, encode ? ntohl (addr) : addr, encode); + + else + { +#if defined (VXWORKS) + int address = ::hostGetByName ((char *) host_name); + return this->set (port_number, encode ? ntohl (address) : address, encode); +#else + hostent hentry; + ACE_HOSTENT_DATA buf; + int error; + + hostent *hp = ACE_OS::gethostbyname_r (host_name, &hentry, + buf, &error); + + if (hp == 0) + { + errno = EINVAL; + return -1; + } + else + { + (void) ACE_OS::memcpy ((void *) &addr, hp->h_addr, hp->h_length); + return this->set (port_number, encode ? ntohl (addr) : addr, encode); + } +#endif /* VXWORKS */ + } +} + +// Initializes a ACE_INET_Addr from a <port_name> and the remote +// <host_name>. + +int +ACE_INET_Addr::set (const char port_name[], + const char host_name[]) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + servent sentry; + ACE_SERVENT_DATA buf; + + servent *sp = ACE_OS::getservbyname_r ((char *) port_name, + "tcp", &sentry, buf); + if (sp == 0) + return -1; + else + return this->set (sp->s_port, host_name, 0); +#endif /* VXWORKS */ +} + +// Initializes a ACE_INET_Addr from a <port_name> and an Internet +// address. + +int +ACE_INET_Addr::set (const char port_name[], + ACE_UINT32 inet_address) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + servent sentry; + ACE_SERVENT_DATA buf; + + servent *sp = ACE_OS::getservbyname_r ((char *) port_name, + "tcp", &sentry, buf); + if (sp == 0) + return -1; + else + return this->set (sp->s_port, inet_address, 0); +#endif /* VXWORKS */ +} + +// Creates a ACE_INET_Addr from a PORT_NUMBER and the remote +// HOST_NAME. + + +ACE_INET_Addr::ACE_INET_Addr (u_short port_number, + const char host_name[]) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + if (this->set (port_number, host_name) == -1) + ACE_ERROR ((LM_ERROR, "ACE_INET_Addr::ACE_INET_Addr")); +} + +// Creates a ACE_INET_Addr from a sockaddr_in structure. + +int +ACE_INET_Addr::set (const sockaddr_in *addr, int len) +{ + ACE_TRACE ("ACE_INET_Addr::set"); + this->ACE_Addr::base_set (AF_INET, len); + ACE_OS::memcpy ((void *) &this->inet_addr_, + (void *) addr, len); + return 0; +} + +// Set a pointer to the address. +void +ACE_INET_Addr::set_addr (void *addr, int len) +{ + ACE_TRACE ("ACE_INET_Addr::set_addr"); + + this->ACE_Addr::base_set (AF_INET, len); + ACE_OS::memcpy ((void *) &this->inet_addr_, + (void *) addr, len); +} + +// Creates a ACE_INET_Addr from a sockaddr_in structure. + + +ACE_INET_Addr::ACE_INET_Addr (const sockaddr_in *addr, int len) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + this->set (addr, len); +} + +// Creates a ACE_INET_Addr from a PORT_NUMBER and an Internet address. + + +ACE_INET_Addr::ACE_INET_Addr (u_short port_number, + ACE_UINT32 inet_address) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + if (this->set (port_number, inet_address) == -1) + ACE_ERROR ((LM_ERROR, "ACE_INET_Addr::ACE_INET_Addr")); +} + +// Creates a ACE_INET_Addr from a PORT_NAME and the remote +// HOST_NAME. + +ACE_INET_Addr::ACE_INET_Addr (const char port_name[], + const char host_name[]) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + if (this->set (port_name, host_name) == -1) + ACE_ERROR ((LM_ERROR, "ACE_INET_Addr::ACE_INET_Addr")); +} + +// Creates a ACE_INET_Addr from a PORT_NAME and an Internet address. + + +ACE_INET_Addr::ACE_INET_Addr (const char* port_name, + ACE_UINT32 inet_address) +{ + ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + if (this->set (port_name, inet_address) == -1) + ACE_ERROR ((LM_ERROR, "ACE_INET_Addr::ACE_INET_Addr")); +} + +int +ACE_INET_Addr::get_host_name (char hostname[], size_t len) const +{ + ACE_TRACE ("ACE_INET_Addr::get_host_name"); +#if defined (VXWORKS) + char name [MAXHOSTNAMELEN + 1]; + int error = ::hostGetByAddr ((int) this->inet_addr_.sin_addr.s_addr, name); + if (error == OK) + { + if (ACE_OS::strlen (name) >= len) + return -1; + else + { + ACE_OS::strcpy (hostname, name); + return 0; + } + } + else + { + errno = error; + return -1; + } +#else + int a_len = sizeof this->inet_addr_.sin_addr.s_addr; + + hostent hentry; + int error; + ACE_HOSTENT_DATA buf; + hostent *hp; + + hp = ACE_OS::gethostbyaddr_r ((char *) &this->inet_addr_.sin_addr, + a_len, this->addr_type_, + &hentry, buf, &error); + if (hp == 0) + { + errno = error; + return -1; + } + else + { + if (ACE_OS::strlen (hp->h_name) >= len) + return -1; + else + { + ACE_OS::strcpy (hostname, hp->h_name); + return 0; + } + } +#endif /* VXWORKS */ +} + +// Return the character representation of the hostname. + +const char * +ACE_INET_Addr::get_host_name (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_host_name"); + +#if defined (VXWORKS) + static char buf[MAXHOSTNAMELEN + 1]; + + ::gethostname (buf, MAXHOSTNAMELEN + 1); +#else + int a_len = sizeof this->inet_addr_.sin_addr.s_addr; + + hostent *hp = ACE_OS::gethostbyaddr ((char *) &this->inet_addr_.sin_addr, + a_len, this->addr_type_); + + if (hp == 0) + return 0; + else + return hp->h_name; +#endif /* VXWORKS */ +} + +void +ACE_INET_Addr::set_port_number (u_short port_number, + int encode) +{ + ACE_TRACE ("ACE_INET_Addr::set_port_number"); + + if (encode) + port_number = htons (port_number); + + this->inet_addr_.sin_port = port_number; +} diff --git a/ace/INET_Addr.h b/ace/INET_Addr.h new file mode 100644 index 00000000000..8fa8b80c7d4 --- /dev/null +++ b/ace/INET_Addr.h @@ -0,0 +1,169 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// INET_Addr.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_INET_ADDR_H) +#define ACE_INET_ADDR_H + +#include "ace/ACE.h" +#include "ace/Addr.h" + +class ACE_Export ACE_INET_Addr : public ACE_Addr + // = TITLE + // Defines the Internet domain address family address format. +{ +public: + // = Initialization methods. + ACE_INET_Addr (void); + // Default constructor. + + ACE_INET_Addr (const ACE_INET_Addr &); + // Copy constructor. + + ACE_INET_Addr (const sockaddr_in *, int len); + // Creates an <ACE_INET_Addr> from a sockaddr_in structure. + + ACE_INET_Addr (u_short port_number, const char host_name[]); + // Creates an <ACE_INET_Addr> from a <port_number> and the remote + // <host_name>. + + ACE_INET_Addr (const char address[]); + // Initializes an <ACE_INET_Addr> from the <address>, which can be + // "ip-number:port-number" (e.g., "tango.cs.wustl.edu:1234" or + // "128.252.166.57:1234"). If there is no ':' in the <address> it + // is assumed to be a port number, with the IP address being + // INADDR_ANY. + + ACE_INET_Addr (u_short port_number, ACE_UINT32 ip_addr = INADDR_ANY); + // Creates an <ACE_INET_Addr> from a <port_number> and an Internet + // <ip_addr>. This method assumes that <port_number> and <ip_addr> + // are in host byte order. + + ACE_INET_Addr (const char port_name[], const char host_name[]); + // Uses <getservbyname> to create an <ACE_INET_Addr> from a + // <port_name> and the remote <host_name>. + + ACE_INET_Addr (const char port_name[], ACE_UINT32 ip_addr); + // Uses <getservbyname> to create an <ACE_INET_Addr> from a + // <port_name> and an Internet <ip_addr>. This method assumes that + // <ip_addr> is in host byte order. + + // = Direct initialization methods (useful after the object has been + // constructed). + int set (const ACE_INET_Addr &); + // Initializes from another <ACE_INET_Addr>. + + int set (u_short port_number, const char host_name[], + int encode = 1); + // Initializes an <ACE_INET_Addr> from a <port_number> and the + // remote <host_name>. If <encode> is enabled then <port_number> is + // converted into network byte order, otherwise it is assumed to be + // in network byte order already and are passed straight through. + + int set (u_short port_number, + ACE_UINT32 ip_addr = INADDR_ANY, + int encode = 1); + // Initializes an <ACE_INET_Addr> from a <port_number> and an + // Internet <ip_addr>. If <encode> is enabled then <port_number> + // and <ip_addr> are converted into network byte order, otherwise + // they are assumed to be in network byte order already and are + // passed straight through. + + int set (const char port_name[], const char host_name[]); + // Uses <getservbyname> to initialize an <ACE_INET_Addr> from a + // <port_name> and the remote <host_name>. + + int set (const char port_name[], ACE_UINT32 ip_addr); + // Uses <getservbyname> to initialize an <ACE_INET_Addr> from a + // <port_name> and an Internet address. This assumes that <ip_addr> + // is already in network byte order. + + int set (const char addr[]); + // Initializes an <ACE_INET_Addr> from the <addr>, which can be + // "ip-number:port-number" (e.g., "tango.cs.wustl.edu:1234" or + // "128.252.166.57:1234"). If there is no ':' in the <address> it + // is assumed to be a port number, with the IP address being + // INADDR_ANY. + + int set (const sockaddr_in *, int len); + // Creates an <ACE_INET_Addr> from a sockaddr_in structure. + + virtual void *get_addr (void) const; + // Return a pointer to the underlying network address. + + virtual void set_addr (void *, int len); + // Set a pointer to the address. + + virtual int addr_to_string (char addr[], size_t) const; + // Transform the current <ACE_INET_Addr> address into string format, + // which is in the form "ip-number:port-number" (e.g., + // "tango.cs.wustl.edu:1234" or "128.252.166.57:1234"). + + virtual int string_to_addr (const char address[]); + // Initializes an <ACE_INET_Addr> from the <address>, which can be + // "ip-number:port-number" (e.g., "tango.cs.wustl.edu:1234" or + // "128.252.166.57:1234"). If there is no ':' in the <address> it + // is assumed to be a port number, with the IP address being + // INADDR_ANY. + + void set_port_number (u_short, int encode = 1); + // Sets the port number without affecting the host name. If + // <encode> is enabled then <port_number> is converted into network + // byte order, otherwise it is assumed to be in network byte order + // already and are passed straight through. + + u_short get_port_number (void) const; + // Return the port number, converting it into host byte order. + + int get_host_name (char hostname[], size_t hostnamelen) const; + // Return the character representation of the name of the host, + // storing it in the <hostname> (which is assumed to be + // <hostnamelen> bytes long). This version is reentrant. + + const char *get_host_name (void) const; + // Return the character representation of the hostname (this version + // is non-reentrant since it returns a pointer to a static data + // area). + + const char *get_host_addr (void) const; + // Return the dotted Internet address. + + ACE_UINT32 get_ip_address (void) const; + // Return the 4-byte IP address, converting it into host byte + // order. + + virtual int operator == (const ACE_Addr &SAP) const; + // Compare two addresses for equality. The addresses are considered + // equal if they contain the same IP address and port number. + + virtual int operator != (const ACE_Addr &SAP) const; + // Compare two addresses for inequality. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + sockaddr_in inet_addr_; + // Underlying representation. +}; + +#if defined (__ACE_INLINE__) +#include "ace/INET_Addr.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_INET_ADDR_H */ diff --git a/ace/INET_Addr.i b/ace/INET_Addr.i new file mode 100644 index 00000000000..1629dc0ecb0 --- /dev/null +++ b/ace/INET_Addr.i @@ -0,0 +1,56 @@ +/* -*- C++ -*- */ +// $Id$ + +// INET_Addr.i + +#include "ace/Log_Msg.h" + +// Return the port number, converting it into host byte order... + +ACE_INLINE u_short +ACE_INET_Addr::get_port_number (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_port_number"); + return ntohs (this->inet_addr_.sin_port); +} + +// Return the address. + +ACE_INLINE void * +ACE_INET_Addr::get_addr (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_addr"); + return (void *) &this->inet_addr_; +} + +// Return the dotted Internet address. + +ACE_INLINE const char * +ACE_INET_Addr::get_host_addr (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_host_addr"); + 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 +ACE_INET_Addr::get_ip_address (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_ip_address"); + return ntohl (ACE_UINT32 (this->inet_addr_.sin_addr.s_addr)); +} + diff --git a/ace/IO_Cntl_Msg.cpp b/ace/IO_Cntl_Msg.cpp new file mode 100644 index 00000000000..2b0d38b8355 --- /dev/null +++ b/ace/IO_Cntl_Msg.cpp @@ -0,0 +1,34 @@ +// IO_Cntl_Msg.cpp +// $Id$ + +#if 0 +/* Forward decl */ +template <class SYNCH> class ACE_Module; + + +class ACE_Module_Link +{ + // = TITLE + // Data structure used to link two modules together + // + // = DESCRIPTION + // +public: + ACE_Module_Link (ACE_Module *m1, ACE_Module *m2): mod_upper_ (m1), mod_lower_ (m2), count_ (0) {} + + ACE_Module *upper (void) { return this->mod_upper_; } + void upper (ACE_Module *u) { this->mod_upper_ = u; } + + ACE_Module *lower (void) { return this->mod_lower_; } + void lower (ACE_Module *l) { this->mod_lower_ = l; } + + int count (void) { return this->count_; } + void count (int c) { this->count_ = c; } + +private: + ACE_Module *mod_upper_; + ACE_Module *mod_lower_; + int count_; +}; +#endif + diff --git a/ace/IO_Cntl_Msg.h b/ace/IO_Cntl_Msg.h new file mode 100644 index 00000000000..7a0fb272cc7 --- /dev/null +++ b/ace/IO_Cntl_Msg.h @@ -0,0 +1,85 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// IO_Cntl_Msg.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_IO_CNTL_MSG_H) +#define ACE_IO_CNTL_MSG_H + +class ACE_Export ACE_IO_Cntl_Msg + // = TITLE + // Data format for IOCTL messages +{ +public: + enum ACE_IO_Cntl_Cmds + { + SET_LWM = 1, // Set the low water mark. + GET_LWM = 2, // Get the low water mark. + SET_HWM = 3, // Set the high water mark. + GET_HWM = 4, // Get the high water mark. + MOD_LINK = 5, // Link modules + MOD_UNLINK = 6 // Unlink modules + }; + + // = Initialization method. + ACE_IO_Cntl_Msg (ACE_IO_Cntl_Cmds c) { this->cmd_ = c; } + // Initialize the control message. + + // = Get/set methods + + ACE_IO_Cntl_Cmds cmd (void) { return this->cmd_; } + // Get command. + + void cmd (ACE_IO_Cntl_Cmds c) { this->cmd_ = c; } + // Set command. + + size_t count (void) { return this->count_; } + // Get count. + + void count (size_t c) { this->count_ = c; } + // Set count. + + int error (void) { return this->error_; } + // Get error. + + void error (int e) { this->error_ = e; } + // Set error. + + int rval (void) { return this->rval_; } + // Get return value. + + void rval (int r) { this->rval_ = r; } + // Set return value. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_IO_Cntl_Cmds cmd_; + // Command. + + size_t count_; + // Count. + + int error_; + // Error. + + int rval_; + // Return value +}; + +#endif /* ACE_IO_CNTL_MSG_H */ diff --git a/ace/IO_Cntl_Msg.i b/ace/IO_Cntl_Msg.i new file mode 100644 index 00000000000..8ab50e712bb --- /dev/null +++ b/ace/IO_Cntl_Msg.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// IO_Cntl_Msg.i diff --git a/ace/IO_SAP.cpp b/ace/IO_SAP.cpp new file mode 100644 index 00000000000..d6fbaca169d --- /dev/null +++ b/ace/IO_SAP.cpp @@ -0,0 +1,124 @@ +// IO_SAP.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/IO_SAP.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_IO_SAP) + +// This is the do-nothing constructor. It does not perform a +// ACE_OS::open system call. + +ACE_IO_SAP::ACE_IO_SAP (void) + : handle_ (ACE_INVALID_HANDLE) +{ + ACE_TRACE ("ACE_IO_SAP::ACE_IO_SAP"); +} + +void +ACE_IO_SAP::dump (void) const +{ + ACE_TRACE ("ACE_IO_SAP::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "handle_ = %d", this->handle_)); + ACE_DEBUG ((LM_DEBUG, "\npid_ = %d", this->pid_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Cache for the process ID. +pid_t ACE_IO_SAP::pid_ = 0; + +// Make the HANDLE_ available for asynchronous I/O (SIGIO), urgent +// data (SIGURG), or non-blocking I/O (ACE_NONBLOCK). + +int +ACE_IO_SAP::enable (int signum) const +{ + ACE_TRACE ("ACE_IO_SAP::enable"); + /* First-time in initialization. */ + if (ACE_IO_SAP::pid_ == 0) + ACE_IO_SAP::pid_ = ACE_OS::getpid (); + +#if !defined(ACE_WIN32) + + switch (signum) + { +#if defined (SIGURG) + case SIGURG: +#if defined (F_SETOWN) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, ACE_IO_SAP::pid_) < 0) + return ACE_IO_SAP::INVALID_HANDLE; + break; +#else + return ACE_IO_SAP::INVALID_HANDLE; +#endif /* F_SETOWN */ +#endif /* SIGURG */ + case SIGIO: +#if defined (F_SETOWN) && defined (FASYNC) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, ACE_IO_SAP::pid_) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; + if (ACE::set_flags (this->handle_, FASYNC) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; + break; +#else + return ACE_IO_SAP::INVALID_HANDLE; +#endif /* F_SETOWN && FASYNC */ + case ACE_NONBLOCK: + if (ACE::set_flags (this->handle_, ACE_NONBLOCK) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; + break; + default: + return ACE_IO_SAP::INVALID_HANDLE; + } + +#endif /* !ACE_WIN32 */ + + return 0; +} + +// Restore the IO_SAP by turning off synchronous I/O or urgent delivery. + +int +ACE_IO_SAP::disable (int signum) const +{ + ACE_TRACE ("ACE_IO_SAP::disable"); + +#if !defined(ACE_WIN32) + + switch (signum) + { +#if defined (SIGURG) + case SIGURG: +#if defined (F_SETOWN) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, 0) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; +#else + return ACE_IO_SAP::INVALID_HANDLE; +#endif /* F_SETOWN */ + break; +#endif /* SIGURG */ + case SIGIO: +#if defined (F_SETOWN) && defined (FASYNC) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, 0) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; + if (ACE::clr_flags (this->handle_, FASYNC) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; +#else + return ACE_IO_SAP::INVALID_HANDLE; +#endif /* F_SETOWN && FASYNC */ + break; + case ACE_NONBLOCK: + if (ACE::clr_flags (this->handle_, ACE_NONBLOCK) == ACE_IO_SAP::INVALID_HANDLE) + return ACE_IO_SAP::INVALID_HANDLE; + break; + default: + return ACE_IO_SAP::INVALID_HANDLE; + } + +#endif /* !ACE_WIN32 */ + + return 0; +} + diff --git a/ace/IO_SAP.h b/ace/IO_SAP.h new file mode 100644 index 00000000000..a57d501c03d --- /dev/null +++ b/ace/IO_SAP.h @@ -0,0 +1,70 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// IO_SAP.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_IO_SAP_H) +#define ACE_IO_SAP_H + +#include "ace/ACE.h" + +class ACE_Export ACE_IO_SAP + // = TITLE + // Defines the member functions for the base class of the ACE_IO_SAP + // abstraction. +{ +public: + enum + { + INVALID_HANDLE = -1 // Be consistent with Winsock + }; + + int control (int cmd, void *) const; + // Interface for ioctl. + + // = Methods for manipulating common I/O descriptor options related to + // files. + int enable (int signum) const; + // Enable signal <signum>. + int disable (int signum) const; + // Disable signal <signum>. + + ACE_HANDLE get_handle (void) const; + // Get the underlying descriptor. + + void set_handle (ACE_HANDLE handle); + // Set the underlying descriptor. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_IO_SAP (void); + // Ensure that ACE_IO_SAP is an abstract base class. + +private: + ACE_HANDLE handle_; + // Underlying I/O descriptor. + + static pid_t pid_; + // Cache the process ID. +}; + +#include "ace/IO_SAP.i" + +#endif /* ACE_IO_SAP_H */ diff --git a/ace/IO_SAP.i b/ace/IO_SAP.i new file mode 100644 index 00000000000..f13fe9db8d7 --- /dev/null +++ b/ace/IO_SAP.i @@ -0,0 +1,33 @@ +/* -*- C++ -*- */ +// $Id$ + +// IO_SAP.i + +// Used to return the underlying handle_. + +inline ACE_HANDLE +ACE_IO_SAP::get_handle (void) const +{ + ACE_TRACE ("ACE_IO_SAP::get_handle"); + return this->handle_; +} + +// Used to set the underlying handle_. + +inline void +ACE_IO_SAP::set_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_IO_SAP::set_handle"); + this->handle_ = handle; +} + +// Provides access to the ACE_OS::ioctl system call. + +inline int +ACE_IO_SAP::control (int cmd, void *arg) const +{ + ACE_TRACE ("ACE_IO_SAP::control"); + return ACE_OS::ioctl (this->handle_, cmd, arg); +} + + diff --git a/ace/IPC_SAP.cpp b/ace/IPC_SAP.cpp new file mode 100644 index 00000000000..74d914d1c4f --- /dev/null +++ b/ace/IPC_SAP.cpp @@ -0,0 +1,148 @@ +// IPC_SAP.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/IPC_SAP.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_IPC_SAP) + +void +ACE_IPC_SAP::dump (void) const +{ + ACE_TRACE ("ACE_IPC_SAP::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "handle_ = %d", this->handle_)); + ACE_DEBUG ((LM_DEBUG, "\npid_ = %d", this->pid_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Cache for the process ID. +pid_t ACE_IPC_SAP::pid_ = 0; + +// This is the do-nothing constructor. It does not perform a +// ACE_OS::socket system call. + +ACE_IPC_SAP::ACE_IPC_SAP (void) + : handle_ (ACE_INVALID_HANDLE) +{ +// ACE_TRACE ("ACE_IPC_SAP::ACE_IPC_SAP"); +} + +// Make the HANDLE_ available for asynchronous I/O (SIGIO), urgent +// data (SIGURG), or non-blocking I/O (ACE_NONBLOCK). + +int +ACE_IPC_SAP::enable (int signum) const +{ + ACE_TRACE ("ACE_IPC_SAP::enable"); + + // First-time in initialization. + if (ACE_IPC_SAP::pid_ == 0) + ACE_IPC_SAP::pid_ = ACE_OS::getpid (); + +#if defined(ACE_WIN32) + switch (signum) + { + case ACE_NONBLOCK: + // nonblocking argument (1) + // blocking: (0) + { + u_long nonblock = 1; + return ACE_OS::ioctl (this->handle_, FIONBIO, &nonblock); + } + default: + errno = ENOTSUP; + return -1; + } +#else + switch (signum) + { +#if defined (SIGURG) + case SIGURG: +#if defined (F_SETOWN) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, ACE_IPC_SAP::pid_) < 0) + return -1; +#else + return -1; +#endif /* F_SETOWN */ + break; +#endif /* SIGURG */ + case SIGIO: +#if defined (F_SETOWN) && defined (FASYNC) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, ACE_IPC_SAP::pid_) == -1) + return -1; + if (ACE::set_flags (this->handle_, FASYNC) == -1) + return -1; +#else + return -1; +#endif /* F_SETOWN && FASYNC */ + break; + case ACE_NONBLOCK: + if (ACE::set_flags (this->handle_, ACE_NONBLOCK) == ACE_INVALID_HANDLE) + return -1; + break; + default: + return -1; + } +#endif /* !ACE_WIN32 */ + return 0; +} + +// Restore the IPC_SAPet by turning off synchronous I/O or urgent +// delivery. + +int +ACE_IPC_SAP::disable (int signum) const +{ + ACE_TRACE ("ACE_IPC_SAP::disable"); + +#if defined(ACE_WIN32) + switch (signum) + { + case ACE_NONBLOCK: + // nonblocking argument (1) + // blocking: (0) + { + u_long nonblock = 0; + return ACE_OS::ioctl (this->handle_, FIONBIO, &nonblock); + } + default: + errno = ENOTSUP; + return -1; + } +#else + switch (signum) + { +#if defined (SIGURG) + case SIGURG: +#if defined (F_SETOWN) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, 0) == -1) + return -1; + break; +#else + return -1; +#endif /* F_SETOWN */ +#endif /* SIGURG */ + case SIGIO: +#if defined (F_SETOWN) && defined (FASYNC) + if (ACE_OS::fcntl (this->handle_, F_SETOWN, 0) == -1) + return -1; + if (ACE::clr_flags (this->handle_, FASYNC) == -1) + return -1; + break; +#else + return -1; +#endif /* F_SETOWN && FASYNC */ + case ACE_NONBLOCK: + if (ACE::clr_flags (this->handle_, ACE_NONBLOCK) == -1) + return -1; + break; + default: + return -1; + } +#endif /* !ACE_WIN32 */ + return 0; +} + diff --git a/ace/IPC_SAP.h b/ace/IPC_SAP.h new file mode 100644 index 00000000000..ee7a4ede41c --- /dev/null +++ b/ace/IPC_SAP.h @@ -0,0 +1,67 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// IPC_SAP.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_IPC_SAP_H) +#define ACE_IPC_SAP_H + +#include "ace/ACE.h" + +class ACE_Export ACE_IPC_SAP + // = TITLE + // Defines the member functions for the base class of the + // ACE_IPC_SAP abstraction. +{ +public: + int control (int cmd, void *) const; + // Interface for ioctl. + + // = Methods for manipulating common I/O descriptor options related + // to sockets. + int enable (int signum) const; + // Enable signal <signum>. + + int disable (int signum) const; + // Disable signal <signum>. + + ACE_HANDLE get_handle (void) const; + // Get the underlying descriptor. + + void set_handle (ACE_HANDLE handle); + // Set the underlying descriptor. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Ensure that ACE_IPC_SAP is an abstract base class. + ACE_IPC_SAP (void); + // Default constructor. + +private: + ACE_HANDLE handle_; + // Underlying I/O descriptor. + + static pid_t pid_; + // Cache the process ID. +}; + +#include "ace/IPC_SAP.i" + +#endif /* ACE_IPC_SAP_H */ diff --git a/ace/IPC_SAP.i b/ace/IPC_SAP.i new file mode 100644 index 00000000000..930be9c991e --- /dev/null +++ b/ace/IPC_SAP.i @@ -0,0 +1,31 @@ +/* -*- C++ -*- */ +// $Id$ + +// IPC_SAP.i + +// Used to return the underlying handle_. + +inline ACE_HANDLE +ACE_IPC_SAP::get_handle (void) const +{ + ACE_TRACE ("ACE_IPC_SAP::get_handle"); + return this->handle_; +} + +// Used to set the underlying handle_. + +inline void +ACE_IPC_SAP::set_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_IPC_SAP::set_handle"); + this->handle_ = handle; +} + +// Provides access to the ACE_OS::ioctl system call. + +inline int +ACE_IPC_SAP::control (int cmd, void *arg) const +{ + ACE_TRACE ("ACE_IPC_SAP::control"); + return ACE_OS::ioctl (this->handle_, cmd, arg); +} diff --git a/ace/LSOCK.cpp b/ace/LSOCK.cpp new file mode 100644 index 00000000000..8b60716ef46 --- /dev/null +++ b/ace/LSOCK.cpp @@ -0,0 +1,121 @@ +// LSOCK.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/LSOCK.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK) + +void +ACE_LSOCK::dump (void) const +{ + ACE_TRACE ("ACE_LSOCK::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "aux_handle_ = %d", this->aux_handle_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_HAS_MSG) +// This routine sends an open file descriptor to <this->handle_>. + +int +ACE_LSOCK::send_handle (const ACE_HANDLE fd) const +{ + ACE_TRACE ("ACE_LSOCK::send_handle"); + unsigned char a[2]; + iovec iov; + msghdr send_msg; + + a[0] = 0xab; + a[1] = 0xcd; + iov.iov_base = (char *) a; + iov.iov_len = sizeof a; + send_msg.msg_iov = &iov; + send_msg.msg_iovlen = 1; + send_msg.msg_name = (char *) 0; + send_msg.msg_namelen = 0; + send_msg.msg_accrights = (char *) &fd; + send_msg.msg_accrightslen = sizeof fd; + + return ACE_OS::sendmsg (this->get_handle (), &send_msg, 0); +} + +// This file receives an open file descriptor from THIS->SOK_FD. +// Note, this routine returns -1 if problems occur, 0 if we recv a +// message that does not have file descriptor in it, and 1 otherwise. + +int +ACE_LSOCK::recv_handle (ACE_HANDLE &fd, char *pbuf, int *len) const +{ + ACE_TRACE ("ACE_LSOCK::recv_handle"); + unsigned char a[2]; + iovec iov; + msghdr recv_msg; + + if (pbuf != 0 && len != 0) + { + iov.iov_base = pbuf; + iov.iov_len = *len; + } + else + { + iov.iov_base = (char *) a; + iov.iov_len = sizeof a; + } + + recv_msg.msg_iov = &iov; + recv_msg.msg_iovlen = 1; + recv_msg.msg_name = (char *) 0; + recv_msg.msg_namelen = 0; + recv_msg.msg_accrights = (char *) &fd; + recv_msg.msg_accrightslen = sizeof fd; + +#if defined (ACE_HAS_STREAMS) + ssize_t nbytes = ACE_OS::recvmsg (this->get_handle (), &recv_msg, 0); + + if (nbytes != ACE_INVALID_HANDLE) + { + if (len != 0) + *len = nbytes; + + if (nbytes == sizeof a + && ((unsigned char *) iov.iov_base)[0] == 0xab + && ((unsigned char *) iov.iov_base)[1] == 0xcd) + return 1; + else + return 0; + } +#else + ssize_t nbytes = ACE_OS::recvmsg (this->get_handle (), &recv_msg, MSG_PEEK); + + if (nbytes != ACE_INVALID_HANDLE) + { + if (nbytes == sizeof a + && ((unsigned char *) iov.iov_base)[0] == 0xab + && ((unsigned char *) iov.iov_base)[1] == 0xcd) + { + recv_msg.msg_accrights = (char *) &fd; + recv_msg.msg_accrightslen = sizeof fd; + + if (ACE_OS::recvmsg (this->get_handle (), &recv_msg, 0) == ACE_INVALID_HANDLE) + return ACE_INVALID_HANDLE; + else + return 1; + } + else + { + if (len != 0) + *len = nbytes; + return 0; + } + } +#endif /* ACE_HAS_STREAMS */ + else + return ACE_INVALID_HANDLE; +} +#endif /* ACE_HAS_MSG */ +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/LSOCK.h b/ace/LSOCK.h new file mode 100644 index 00000000000..6c7c922a830 --- /dev/null +++ b/ace/LSOCK.h @@ -0,0 +1,70 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// LSOCK.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOCAL_SOCK_H) +#define ACE_LOCAL_SOCK_H + +#include "ace/SOCK.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_LSOCK + // = TITLE + // Create a Local ACE_SOCK, which is used for passing file + // descriptors. +{ +public: +#if defined (ACE_HAS_MSG) + int send_handle (const ACE_HANDLE handle) const; + // Send an open FD to another process. + + int recv_handle (ACE_HANDLE &handles, + char *pbuf = 0, + int *len = 0) const; + // Recv an open FD from another process. +#endif /* ACE_HAS_MSG */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Ensure that ACE_LSOCK is an abstract base class + + ACE_LSOCK (void); + // Default constructor. + + ACE_LSOCK (ACE_HANDLE handle); + // Initialize based on <handle> + + ACE_HANDLE get_handle (void) const; + // Get handle. + + void set_handle (ACE_HANDLE handle); + // Set handle. + +private: + ACE_HANDLE aux_handle_; + // An auxiliary handle used to avoid virtual base classes... +}; + +#include "ace/LSOCK.i" + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_LOCAL_SOCK_H */ diff --git a/ace/LSOCK.i b/ace/LSOCK.i new file mode 100644 index 00000000000..cddc2db5812 --- /dev/null +++ b/ace/LSOCK.i @@ -0,0 +1,39 @@ +/* -*- C++ -*- */ +// $Id$ + +// LSOCK.i + +// Simple-minded constructor. + +inline +ACE_LSOCK::ACE_LSOCK (void) +{ + ACE_TRACE ("ACE_LSOCK::ACE_LSOCK"); +} + +// Sets the underlying file descriptor. + +inline void +ACE_LSOCK::set_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_LSOCK::set_handle"); + this->aux_handle_ = handle; +} + +// Gets the underlying file descriptor. + +inline ACE_HANDLE +ACE_LSOCK::get_handle (void) const +{ + ACE_TRACE ("ACE_LSOCK::get_handle"); + return this->aux_handle_; +} + +// Sets the underlying file descriptor. + +inline +ACE_LSOCK::ACE_LSOCK (ACE_HANDLE handle) + : aux_handle_ (handle) +{ + ACE_TRACE ("ACE_LSOCK::ACE_LSOCK"); +} diff --git a/ace/LSOCK_Acceptor.cpp b/ace/LSOCK_Acceptor.cpp new file mode 100644 index 00000000000..db8c374d519 --- /dev/null +++ b/ace/LSOCK_Acceptor.cpp @@ -0,0 +1,98 @@ +// LSOCK_Acceptor.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/LSOCK_Acceptor.h" + +#if !defined (__ACE_INLINE__) +#include "ace/LSOCK_Acceptor.i" +#endif /* __ACE_INLINE__ */ + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Acceptor) + +// Return the local endpoint address. + +int +ACE_LSOCK_Acceptor::get_local_addr (ACE_Addr &a) const +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::get_local_addr"); + a = this->local_addr_; + return 0; +} + +void +ACE_LSOCK_Acceptor::dump (void) const +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->local_addr_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Do nothing routine for constructor. + +ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor (void) +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor"); +} + +int +ACE_LSOCK_Acceptor::open (const ACE_Addr &remote_sap, + int reuse_addr, + int protocol_family, + int backlog, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::open"); + this->local_addr_ = *((ACE_UNIX_Addr *) &remote_sap); // This is a gross hack... + return ACE_SOCK_Acceptor::open (remote_sap, reuse_addr, + protocol_family, backlog, protocol); +} + +// General purpose routine for performing server ACE_SOCK creation. + +ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor (const ACE_Addr &remote_sap, + int reuse_addr, + int protocol_family, + int backlog, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor"); + if (this->open (remote_sap, reuse_addr, + protocol_family, backlog, protocol) == -1) + ACE_ERROR ((LM_ERROR, "ACE_LSOCK_Acceptor::ACE_LSOCK_Acceptor")); +} + +// General purpose routine for accepting new connections. + +int +ACE_LSOCK_Acceptor::accept (ACE_LSOCK_Stream &new_local_ipc_sap, + ACE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart) const +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::accept"); + ACE_HANDLE new_handle = + ACE_SOCK_Acceptor::shared_accept (remote_addr, timeout, restart); + new_local_ipc_sap.set_handle (new_handle); + return new_handle == ACE_INVALID_HANDLE ? -1 : 0; +} + +// Close down the UNIX domain stream and remove the rendezvous point +// from the file system. + +int +ACE_LSOCK_Acceptor::remove (void) +{ + ACE_TRACE ("ACE_LSOCK_Acceptor::remove"); + int result = this->close (); + return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1 + || result == -1 ? -1 : 0; +} + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/LSOCK_Acceptor.h b/ace/LSOCK_Acceptor.h new file mode 100644 index 00000000000..2c262e2b66a --- /dev/null +++ b/ace/LSOCK_Acceptor.h @@ -0,0 +1,84 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// LSOCK_Aceeptor.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOCAL_SOCK_ACCEPTOR_H) +#define ACE_LOCAL_SOCK_ACCEPTOR_H + +#include "ace/SOCK_Acceptor.h" +#include "ace/UNIX_Addr.h" +#include "ace/LSOCK_Stream.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_LSOCK_Acceptor : public ACE_SOCK_Acceptor + // = TITLE + // Defines the format and interface for the acceptor side of the + // local ACE_SOCK ACE_Stream. +{ +public: + // = Initialization methods. + ACE_LSOCK_Acceptor (void); + // Default constructor. + + ACE_LSOCK_Acceptor (const ACE_Addr &local_sap, + int reuse_addr = 0, + int protocol_family = PF_UNIX, + int backlog = 5, + int protocol = 0); + // Initiate a passive mode socket. + + int open (const ACE_Addr &local_sap, + int reuse_addr = 0, + int protocol_family = PF_UNIX, + int backlog = 5, + int protocol = 0); + // Initiate a passive mode socket. + + int accept (ACE_LSOCK_Stream &new_ipc_sap, + ACE_Addr * = 0, + ACE_Time_Value *timeout = 0, + int restart = 1) const; + // Accept a new data transfer connection. + + int remove (void); + // Close down the ACE_LSOCK and remove the rendezvous point from the + // file system. + + int get_local_addr (ACE_Addr &) const; + // Return the local endpoint address. + + // = Meta-type info + typedef ACE_UNIX_Addr PEER_ADDR; + typedef ACE_LSOCK_Stream PEER_STREAM; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_UNIX_Addr local_addr_; + // Address of our rendezvous point. +}; + +#if defined (__ACE_INLINE__) +#include "ace/LSOCK_Acceptor.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_LOCAL_SOCK_ACCEPTOR_H */ diff --git a/ace/LSOCK_Acceptor.i b/ace/LSOCK_Acceptor.i new file mode 100644 index 00000000000..e873fd02822 --- /dev/null +++ b/ace/LSOCK_Acceptor.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// LSOCK_Acceptor.i diff --git a/ace/LSOCK_CODgram.cpp b/ace/LSOCK_CODgram.cpp new file mode 100644 index 00000000000..f2c357ebd0d --- /dev/null +++ b/ace/LSOCK_CODgram.cpp @@ -0,0 +1,54 @@ +// LSOCK_CODgram.cpp +// $Id$ + +/* Contains the definitions for the Local ACE_SOCK connection-oriented + datagram abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/LSOCK_CODgram.h" +#include "ace/Log_Msg.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_CODgram) + +void +ACE_LSOCK_CODgram::dump (void) const +{ + ACE_TRACE ("ACE_LSOCK_CODgram::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_SOCK_CODgram::dump (); + ACE_LSOCK::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +/* Here's the general-purpose open routine. */ + +int +ACE_LSOCK_CODgram::open (const ACE_Addr &remote, + const ACE_Addr &local, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_CODgram::open"); + if (ACE_SOCK_CODgram::open (remote, local, protocol_family, + protocol) == -1) + return -1; + ACE_LSOCK::set_handle (this->get_handle ()); + return 0; +} + +/* Create a local ACE_SOCK datagram. */ + +ACE_LSOCK_CODgram::ACE_LSOCK_CODgram (const ACE_Addr &remote, + const ACE_Addr &local, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_CODgram::ACE_LSOCK_CODgram"); + if (this->open (remote, local, protocol_family, + protocol) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_LSOCK_CODgram")); +} +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/LSOCK_CODgram.h b/ace/LSOCK_CODgram.h new file mode 100644 index 00000000000..360148cbbf7 --- /dev/null +++ b/ace/LSOCK_CODgram.h @@ -0,0 +1,65 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// LSOCK_CODgram.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOCAL_SOCK_CODGRAM_H) +#define ACE_LOCAL_SOCK_CODGRAM_H + +#include "ace/LSOCK.h" +#include "ace/SOCK_CODgram.h" +#include "ace/Addr.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_LSOCK_CODgram : public ACE_SOCK_CODgram, public ACE_LSOCK + // = TITLE + // Defines the member functions for the ACE_LSOCK + // connected datagram abstraction. +{ +public: + // = Initialization methods. + ACE_LSOCK_CODgram (void); + // Default constructor. + + ACE_LSOCK_CODgram (const ACE_Addr &remote_sap, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int protocol_family = PF_UNIX, + int protocol = 0); + // Initiate a connected-datagram. + + int open (const ACE_Addr &remote_sap, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int protocol_family = PF_UNIX, + int protocol = 0); + // Initiate a connected-datagram. + + ACE_HANDLE get_handle (void) const; + // Get underlying handle. + + void set_handle (ACE_HANDLE); + // Set underlying handle. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/LSOCK_CODgram.i" + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_LOCAL_SOCK_CODGRAM_H */ diff --git a/ace/LSOCK_CODgram.i b/ace/LSOCK_CODgram.i new file mode 100644 index 00000000000..40b2330cdcd --- /dev/null +++ b/ace/LSOCK_CODgram.i @@ -0,0 +1,27 @@ +/* -*- C++ -*- */ +// $Id$ + +// LSOCK_CODgram.i + +// Do nothing constructor. + +inline +ACE_LSOCK_CODgram::ACE_LSOCK_CODgram (void) +{ + ACE_TRACE ("ACE_LSOCK_CODgram::ACE_LSOCK_CODgram"); +} + +inline void +ACE_LSOCK_CODgram::set_handle (ACE_HANDLE h) +{ + ACE_TRACE ("ACE_LSOCK_CODgram::set_handle"); + this->ACE_SOCK_CODgram::set_handle (h); + this->ACE_LSOCK::set_handle (h); +} + +inline ACE_HANDLE +ACE_LSOCK_CODgram::get_handle (void) const +{ + ACE_TRACE ("ACE_LSOCK_CODgram::get_handle"); + return this->ACE_SOCK_CODgram::get_handle (); +} diff --git a/ace/LSOCK_Connector.cpp b/ace/LSOCK_Connector.cpp new file mode 100644 index 00000000000..07c1317d341 --- /dev/null +++ b/ace/LSOCK_Connector.cpp @@ -0,0 +1,49 @@ +// LSOCK_Connector.cpp +// $Id$ + +/* Defines the format and interface for the connector side of the + local ACE_SOCK ACE_Stream. */ + +#define ACE_BUILD_DLL +#include "ace/LSOCK_Connector.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Connector) + +void +ACE_LSOCK_Connector::dump (void) const +{ + ACE_TRACE ("ACE_LSOCK_Connector::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_LSOCK_Connector::ACE_LSOCK_Connector (void) +{ + ACE_TRACE ("ACE_LSOCK_Connector::ACE_LSOCK_Connector"); +} + +// Establish a connection. +ACE_LSOCK_Connector::ACE_LSOCK_Connector (ACE_LSOCK_Stream &new_stream, + const ACE_UNIX_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + int protocol_family, + int protocol) + : ACE_SOCK_Connector (new_stream, remote_sap, timeout, + local_sap, reuse_addr, flags, perms, + protocol_family, protocol) +{ + ACE_TRACE ("ACE_LSOCK_Connector::ACE_LSOCK_Connector"); + // This is necessary due to the weird inheritance relationships of + // ACE_LSOCK_Stream. + new_stream.set_handle (new_stream.get_handle ()); +} + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/LSOCK_Connector.h b/ace/LSOCK_Connector.h new file mode 100644 index 00000000000..0abd55045f3 --- /dev/null +++ b/ace/LSOCK_Connector.h @@ -0,0 +1,97 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// LSOCK_Connector.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOCAL_SOCK_CONNECTOR_H) +#define ACE_LOCAL_SOCK_CONNECTOR_H + +#include "ace/SOCK_Connector.h" +#include "ace/LSOCK_Stream.h" +#include "ace/UNIX_Addr.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_LSOCK_Connector : public ACE_SOCK_Connector + // = TITLE + // Defines the format and interface for the connector side of the + // local ACE_SOCK ACE_Stream. +{ +public: + // = Initialization methods. + ACE_LSOCK_Connector (void); + // Default constructor. + + ACE_LSOCK_Connector (ACE_LSOCK_Stream &new_stream, + const ACE_UNIX_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = 0, + int perms = 0, + int protocol_family = PF_UNIX, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + int connect (ACE_LSOCK_Stream &new_stream, + const ACE_UNIX_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = 0, + int perms = 0, + int protcol_family = PF_UNIX, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + // = Meta-type info + typedef ACE_UNIX_Addr PEER_ADDR; + typedef ACE_LSOCK_Stream PEER_STREAM; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/LSOCK_Connector.i" + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_LOCAL_SOCK_CONNECTOR_H */ diff --git a/ace/LSOCK_Connector.i b/ace/LSOCK_Connector.i new file mode 100644 index 00000000000..fdd9834a444 --- /dev/null +++ b/ace/LSOCK_Connector.i @@ -0,0 +1,29 @@ +/* -*- C++ -*- */ +// $Id$ + +// LSOCK_Connector.i + +// Establish a connection. + +inline int +ACE_LSOCK_Connector::connect (ACE_LSOCK_Stream &new_stream, + const ACE_UNIX_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_Connector::connect"); + int result = ACE_SOCK_Connector::connect (new_stream, remote_sap, + timeout, local_sap, + reuse_addr, flags, perms, + protocol_family, protocol); + if (result != -1) + // This is necessary due to the weird inheritance relationships of ACE_LSOCK_Stream. + new_stream.set_handle (new_stream.get_handle ()); + return result; +} + diff --git a/ace/LSOCK_Dgram.cpp b/ace/LSOCK_Dgram.cpp new file mode 100644 index 00000000000..621cebbdaf5 --- /dev/null +++ b/ace/LSOCK_Dgram.cpp @@ -0,0 +1,60 @@ +// LSOCK_Dgram.cpp +// $Id$ + +/* Defines the member functions for the Local ACE_SOCK datagram + abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/LSOCK_Dgram.h" +#include "ace/Log_Msg.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Dgram) + +void +ACE_LSOCK_Dgram::dump (void) const +{ + ACE_TRACE ("ACE_LSOCK_Dgram::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_SOCK_Dgram::dump (); + ACE_LSOCK::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +/* The "do nothing" constructor. */ + +ACE_LSOCK_Dgram::ACE_LSOCK_Dgram (void) +{ + ACE_TRACE ("ACE_LSOCK_Dgram::ACE_LSOCK_Dgram"); +} + +/* Here's the general-purpose open routine. */ + +int +ACE_LSOCK_Dgram::open (const ACE_Addr &local, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_Dgram::open"); + if (ACE_SOCK_Dgram::open (local, protocol_family, + protocol) == -1) + return -1; + ACE_LSOCK::set_handle (this->ACE_SOCK_Dgram::get_handle ()); + return 0; +} + +/* Create a local ACE_SOCK datagram. */ + +ACE_LSOCK_Dgram::ACE_LSOCK_Dgram (const ACE_Addr &local, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_LSOCK_Dgram::ACE_LSOCK_Dgram"); + if (this->open (local, protocol_family, + protocol) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_LSOCK_Dgram")); +} + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/LSOCK_Dgram.h b/ace/LSOCK_Dgram.h new file mode 100644 index 00000000000..ec63e15a34e --- /dev/null +++ b/ace/LSOCK_Dgram.h @@ -0,0 +1,61 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// LSOCK_Dgram.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOCAL_SOCK_DGRAM_H) +#define ACE_LOCAL_SOCK_DGRAM_H + +#include "ace/SOCK_Dgram.h" +#include "ace/LSOCK.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_LSOCK_Dgram : public ACE_SOCK_Dgram, public ACE_LSOCK + // = TITLE + // Create a Local ACE_SOCK datagram. +{ +public: + // = Initialization methods. + ACE_LSOCK_Dgram (void); + // Default constructor. + + ACE_LSOCK_Dgram (const ACE_Addr &local, + int protocol_family = PF_UNIX, + int protocol = 0); + // Initiate a local dgram. + + int open (const ACE_Addr &local, + int protocol_family = PF_UNIX, + int protocol = 0); + // Initiate a local dgram. + + ACE_HANDLE get_handle (void) const; + // Get handle. + + void set_handle (ACE_HANDLE); + // Set handle. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/LSOCK_Dgram.i" + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_LOCAL_SOCK_DGRAM_H */ diff --git a/ace/LSOCK_Dgram.i b/ace/LSOCK_Dgram.i new file mode 100644 index 00000000000..51b03bb8c89 --- /dev/null +++ b/ace/LSOCK_Dgram.i @@ -0,0 +1,20 @@ +/* -*- C++ -*- */ +// $Id$ + +// LSOCK_Dgram.i + +inline void +ACE_LSOCK_Dgram::set_handle (ACE_HANDLE h) +{ + ACE_TRACE ("ACE_LSOCK_Dgram::set_handle"); + this->ACE_SOCK_Dgram::set_handle (h); + this->ACE_LSOCK::set_handle (h); +} + +inline ACE_HANDLE +ACE_LSOCK_Dgram::get_handle (void) const +{ + ACE_TRACE ("ACE_LSOCK_Dgram::get_handle"); + return this->ACE_SOCK_Dgram::get_handle (); +} + diff --git a/ace/LSOCK_Stream.cpp b/ace/LSOCK_Stream.cpp new file mode 100644 index 00000000000..108401fc1a1 --- /dev/null +++ b/ace/LSOCK_Stream.cpp @@ -0,0 +1,69 @@ +// LSOCK_Stream.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/LSOCK_Stream.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_LSOCK_Stream) + +void +ACE_LSOCK_Stream::dump (void) const +{ + ACE_TRACE ("ACE_LSOCK_Stream::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_SOCK_Stream::dump (); + ACE_LSOCK::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_HAS_MSG) + +// Send a readv-style vector of buffers, along with an open I/O +// handle. + +ssize_t +ACE_LSOCK_Stream::send_msg (const iovec iov[], + size_t n, + int fd) +{ + ACE_TRACE ("ACE_LSOCK_Stream::send_msg"); + msghdr send_msg; + + send_msg.msg_iov = (iovec *) iov; + send_msg.msg_iovlen = n; + send_msg.msg_name = (char *) 0; + send_msg.msg_namelen = 0; + send_msg.msg_accrights = (char *) &fd; + send_msg.msg_accrightslen = sizeof fd; + + return ACE_OS::sendmsg (this->ACE_SOCK_Stream::get_handle (), + &send_msg, 0); +} + +// Read a readv-style vector of buffers, along with an open I/O +// handle. + +ssize_t +ACE_LSOCK_Stream::recv_msg (iovec iov[], + size_t n, + int &fd) +{ + ACE_TRACE ("ACE_LSOCK_Stream::recv_msg"); + msghdr recv_msg; + + recv_msg.msg_iov = (iovec *) iov; + recv_msg.msg_iovlen = n; + recv_msg.msg_name = (char *) 0; + recv_msg.msg_namelen = 0; + recv_msg.msg_accrights = (char *) &fd; + recv_msg.msg_accrightslen = sizeof fd; + + return ACE_OS::recvmsg (this->ACE_SOCK_Stream::get_handle (), + &recv_msg, 0); +} +#endif /* ACE_HAS_MSG */ +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/LSOCK_Stream.h b/ace/LSOCK_Stream.h new file mode 100644 index 00000000000..be37419b15b --- /dev/null +++ b/ace/LSOCK_Stream.h @@ -0,0 +1,57 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// LSOCK_Stream.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOCAL_SOCK_STREAM_H) +#define ACE_LOCAL_SOCK_STREAM_H + +#include "ace/SOCK_Stream.h" +#include "ace/LSOCK.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_LSOCK_Stream : public ACE_SOCK_Stream, public ACE_LSOCK + // = TITLE + // Create a Local ACE_SOCK stream. +{ +public: + // = Send/recv methods. + ssize_t send_msg (const iovec iov[], size_t n, int fd); + // Send iovecs via <::writev>. + + ssize_t recv_msg (iovec iov[], size_t n, int &fd); + // Send iovecs via <::writev>. + + ACE_HANDLE get_handle (void) const; + // Get handle. + void set_handle (ACE_HANDLE fd); + // Overrides set_handle from the base classes. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int get_remote_addr (ACE_Addr &) const; + // Do not allow this function to percolate up to this interface... +}; + +#include "ace/LSOCK_Stream.i" + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_LOCAL_SOCK_STREAM_H */ diff --git a/ace/LSOCK_Stream.i b/ace/LSOCK_Stream.i new file mode 100644 index 00000000000..e76afa8d240 --- /dev/null +++ b/ace/LSOCK_Stream.i @@ -0,0 +1,25 @@ +/* -*- C++ -*- */ +// $Id$ + +// LSOCK_Stream.i + +// Sets both the file descriptors... Overrides handle from the base +// classes. + +inline void +ACE_LSOCK_Stream::set_handle (ACE_HANDLE fd) +{ + ACE_TRACE ("ACE_LSOCK_Stream::set_handle"); + this->ACE_SOCK_Stream::set_handle (fd); + this->ACE_LSOCK::set_handle (fd); +} + +inline ACE_HANDLE +ACE_LSOCK_Stream::get_handle (void) const +{ + ACE_TRACE ("ACE_LSOCK_Stream::get_handle"); + return this->ACE_SOCK_Stream::get_handle (); +} + + + diff --git a/ace/Local_Name_Space.cpp b/ace/Local_Name_Space.cpp new file mode 100644 index 00000000000..444e7507a13 --- /dev/null +++ b/ace/Local_Name_Space.cpp @@ -0,0 +1,155 @@ +// Local_Name_Space.cpp +// $Id$ + +#if !defined (ACE_LOCAL_NAME_SPACE_C) +#define ACE_LOCAL_NAME_SPACE_C + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/ACE.h" +#include "ace/Local_Name_Space.h" + +ACE_USHORT16 * +ACE_NS_String::fast_rep (void) const +{ + ACE_TRACE ("ACE_NS_String::fast_rep"); + return this->rep_; +} + +ACE_NS_String::operator ACE_WString () const +{ + ACE_TRACE ("ACE_NS_String::operator ACE_WString"); + return ACE_WString (this->rep_, (this->len_ / sizeof (ACE_USHORT16)) - 1); +} + +size_t +ACE_NS_String::len (void) const +{ + ACE_TRACE ("ACE_NS_String::len"); + return this->len_; +} + +char * +ACE_NS_String::char_rep (void) const +{ + ACE_TRACE ("ACE_NS_String::char_rep"); + ACE_WString w_string (this->rep_, (this->len_ / sizeof (ACE_USHORT16)) - 1); + return w_string.char_rep (); +} + +ACE_NS_String::ACE_NS_String (void) + : rep_ (0), + len_ (0) +{ + ACE_TRACE ("ACE_NS_String::ACE_NS_String"); +} + +ACE_NS_String::ACE_NS_String (const ACE_WString &s) + : rep_ (s.fast_rep ()), + len_ ((s.length () + 1) * sizeof (ACE_USHORT16)) +{ + ACE_TRACE ("ACE_NS_String::ACE_NS_String"); +} + +int +ACE_NS_String::strstr (const ACE_NS_String &s) const +{ + ACE_TRACE ("ACE_NS_String::strstr"); + + if (this->len_ < s.len_) + // If they're larger than we are they can't be a substring of us! + return -1; + else if (this->len_ == s.len_) + // Check if we're equal. + return *this == s ? 0 : -1; + else + { + // They're smaller than we are... + size_t len = (this->len_ - s.len_) / sizeof (ACE_USHORT16); + size_t pat_len = s.len_ / sizeof (ACE_USHORT16) - 1; + + for (size_t i = 0; i <= len; i++) + { + size_t j; + + for (j = 0; j < pat_len; j++) + if (this->rep_[i + j] != s.rep_[j]) + break; + + if (j == pat_len) + // Found a match! Return the index. + return i; + } + + return -1; + } +} + +int +ACE_NS_String::operator == (const ACE_NS_String &s) const +{ + ACE_TRACE ("ACE_NS_String::operator =="); + return this->len_ == s.len_ + && ACE_OS::memcmp ((void *) this->rep_, + (void *) s.rep_, this->len_) == 0; +} + +ACE_NS_String::ACE_NS_String (ACE_USHORT16 *dst, + const ACE_USHORT16 *src, + size_t bytes) + : len_ (bytes), + rep_ (dst) +{ + ACE_TRACE ("ACE_NS_String::ACE_NS_String"); + ACE_OS::memcpy (this->rep_, src, bytes); +} + +ACE_NS_Internal::ACE_NS_Internal (void) +{ +} + +ACE_NS_Internal::ACE_NS_Internal (ACE_NS_String &value, const char *type) + : value_ (value), + type_ (type) +{ + ACE_TRACE ("ACE_NS_Internal::ACE_NS_Internal"); +} + +int +ACE_NS_Internal::operator == (const ACE_NS_Internal &s) const +{ + ACE_TRACE ("ACE_NS_Internal::operator =="); + return this->value_ == s.value_; +} + +ACE_NS_String +ACE_NS_Internal::value (void) +{ + ACE_TRACE ("ACE_NS_Internal::value"); + return this->value_; +} + +const char * +ACE_NS_Internal::type (void) +{ + ACE_TRACE ("ACE_NS_Internal::type"); + return this->type_; +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Unbounded_Set<ACE_Name_Binding>; +template class ACE_Unbounded_Set_Iterator<ACE_Name_Binding>; +template class ACE_Unbounded_Set<ACE_WString>; +template class ACE_Unbounded_Set_Iterator<ACE_WString>; +template class ACE_Set_Node<ACE_WString>; +template class ACE_Set_Node<ACE_Name_Binding>; +template class ACE_Guard<ACE_RW_Process_Mutex>; +template class ACE_Read_Guard<ACE_RW_Process_Mutex>; +template class ACE_Write_Guard<ACE_RW_Process_Mutex>; +template class ACE_Malloc<ACE_MMAP_Memory_Pool, ACE_RW_Process_Mutex>; +template class ACE_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>; +template class ACE_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex>; +template class ACE_Map_Entry <ACE_NS_String, ACE_NS_Internal>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ + +#endif /* ACE_LOCAL_NAME_SPACE_C */ diff --git a/ace/Local_Name_Space.h b/ace/Local_Name_Space.h new file mode 100644 index 00000000000..e02d9c288b6 --- /dev/null +++ b/ace/Local_Name_Space.h @@ -0,0 +1,113 @@ +/* -*- C++ -*- */ +// $Id$ + +/*-*- C++ -*- */ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Local_Name_Space +// +// = AUTHOR +// Prashant Jain (pjain@cs.wustl.edu), Irfan Pyarali +// (irfan@wuerl.wustl.edu), and Douglas C. Schmidt +// (schmidt@cs.wustl.edu). +// +// ============================================================================ + +#if !defined (ACE_LOCAL_NAME_SPACE_H) +#define ACE_LOCAL_NAME_SPACE_H + +#include "ace/Map_Manager.h" +#include "ace/Service_Config.h" +#include "ace/SString.h" +#include "ace/Set.h" +#include "ace/Malloc.h" +#include "ace/Synch.h" + +class ACE_Export ACE_NS_String + // = TITLE + // This class and ACE_NS_Internal are used as Adapters to work + // with the Map_Manager. + // + // = DESCRIPTION + // In order to work correctly, this class must be able to + // convert back and forth with ACE_WStrings. Note that this + // class must not have a destructor since otherwise we'll have + // problems... +{ +public: + // = Initialization. + ACE_NS_String (void); + // Default "no-op" constructor. + + ACE_NS_String (ACE_USHORT16 *dst, + const ACE_USHORT16 *src, + size_t len); + // Initialization method. + + ACE_NS_String (const ACE_WString &); + // Converts an ACE_WString to an ACE_NS_String; + + operator ACE_WString () const; + // Converts an ACE_NS_String to fresh copy of an ACE_WString; + + char *char_rep (void) const; + // Return the ASCII character representation. + + int strstr (const ACE_NS_String &) const; + // Matches on substrings. + + int operator == (const ACE_NS_String &) const; + // Compare an ACE_NS_String. + + size_t len (void) const; + // Returns length of the string + + ACE_USHORT16 *fast_rep (void) const; + // Returns the underlying representation. + +private: + size_t len_; + // Length of the string. + + ACE_USHORT16 *rep_; + // This actually points into shared/persistent memory. +}; + +class ACE_Export ACE_NS_Internal + // = TITLE + // This class and ACE_NS_String are used as Adapters to work + // with the Map_Manager. +{ +public: + ACE_NS_Internal (void); + // No-op constructor. + + ACE_NS_Internal (ACE_NS_String &value, const char *type); + // Constructor. + + int operator == (const ACE_NS_Internal &) const; + // Compare an ACE_NS_Internal + + ACE_NS_String value (void); + // Return value. + + const char *type (void); + // Return type. + +private: + ACE_NS_String value_; + // Contains the value of the string. + + const char *type_; + // Contains the type of the string. +}; + +// Include the ACE_Local_Name_Space templates stuff at this point. +#include "ace/Local_Name_Space_T.h" + +#endif /* ACE_LOCAL_NAME_SPACE_H */ diff --git a/ace/Local_Name_Space_T.cpp b/ace/Local_Name_Space_T.cpp new file mode 100644 index 00000000000..557ed0888d6 --- /dev/null +++ b/ace/Local_Name_Space_T.cpp @@ -0,0 +1,673 @@ +// Local_Name_Space_T.cpp +// $Id$ + +#if !defined (ACE_LOCAL_NAME_SPACE_T_C) +#define ACE_LOCAL_NAME_SPACE_T_C + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/ACE.h" +#include "ace/Local_Name_Space.h" + +template <class ALLOCATOR> +ACE_Name_Space_Map<ALLOCATOR>::ACE_Name_Space_Map (ALLOCATOR *allocator) + : MAP_MANAGER (allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::ACE_Name_Space_Map"); +} + +#if defined (ACE_WIN32) +template <class ALLOCATOR> int +ACE_Name_Space_Map<ALLOCATOR>::remap (EXCEPTION_POINTERS *ep, + ALLOCATOR* allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::remap"); + + void *addr = (void *) ep->ExceptionRecord->ExceptionInformation[1]; + + // The following requires Memory Pool to have ::remap() + // defined. Thus currently this will only work for + // ACE_MMap_Memory_Pool. + if (allocator->allocator ().memory_pool ().remap (addr) == -1) + // Kick it upstairs... + return (DWORD) EXCEPTION_CONTINUE_SEARCH; + +#if __X86__ + // This is 80x86-specific. + ep->ContextRecord->Edi = (DWORD) addr; +#elif __MIPS__ + ep->ContextRecord->IntA0 = + ep->ContextRecord->IntV0 = (DWORD) addr; + ep->ContextRecord->IntT5 = ep->ContextRecord->IntA0 + 3; +#endif /* __X86__ */ + // Resume execution at the original point of "failure." + return (DWORD) EXCEPTION_CONTINUE_EXECUTION; +} +#endif /* ACE_WIN32 */ + +template <class ALLOCATOR> int +ACE_Name_Space_Map<ALLOCATOR>::close (ALLOCATOR* allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::close"); + + this->allocator_ = allocator; + return this->close_i (); +} + +template <class ALLOCATOR> int +ACE_Name_Space_Map<ALLOCATOR>::bind (const ACE_NS_String &ext_id, + const ACE_NS_Internal &int_id, + ALLOCATOR* allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::bind"); + int result = 0; + + this->allocator_ = allocator; + + // Note that we *must* use structured exception handling here + // because (1) we may need to commit virtual memory pages and (2) + // C++ exception handling doesn't support resumption. + ACE_SEH_TRY { + result = this->bind_i (ext_id, int_id); + } + ACE_SEH_EXCEPT (this->remap (GetExceptionInformation (), allocator)) { + } + return result; +} + +template <class ALLOCATOR> int +ACE_Name_Space_Map<ALLOCATOR>::unbind (const ACE_NS_String &ext_id, + ACE_NS_Internal &int_id, + ALLOCATOR* allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::unbind"); + int result = 0; + this->allocator_ = allocator; + + // Note that we *must* use structured exception handling here + // because (1) we may need to commit virtual memory pages and (2) + // C++ exception handling doesn't support resumption. + ACE_SEH_TRY { + result = this->unbind_i (ext_id, int_id); + } + ACE_SEH_EXCEPT (this->remap (GetExceptionInformation (), allocator)) { + } + return result; +} + +template <class ALLOCATOR> int +ACE_Name_Space_Map<ALLOCATOR>::rebind (const ACE_NS_String &ext_id, + const ACE_NS_Internal &int_id, + ACE_NS_String &old_ext_id, + ACE_NS_Internal &old_int_id, + ALLOCATOR* allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::rebind"); + int result = 0; + this->allocator_ = allocator; + + // Note that we *must* use structured exception handling here + // because (1) we may need to commit virtual memory pages and (2) + // C++ exception handling doesn't support resumption. + ACE_SEH_TRY { + result = this->rebind_i (ext_id, int_id, old_ext_id, old_int_id); + } + ACE_SEH_EXCEPT (this->remap (GetExceptionInformation (), allocator)) { + } + return result; +} + +template <class ALLOCATOR> int +ACE_Name_Space_Map<ALLOCATOR>::find (const ACE_NS_String &ext_id, + ACE_NS_Internal &int_id, + ALLOCATOR* allocator) +{ + ACE_TRACE ("ACE_Name_Space_Map::find"); + int result = 0; + this->allocator_ = allocator; + + // Note that we *must* use structured exception handling here + // because (1) we may need to commit virtual memory pages and (2) + // C++ exception handling doesn't support resumption. + ACE_SEH_TRY { + result = this->find_i (ext_id, int_id); + } + ACE_SEH_EXCEPT (this->remap (GetExceptionInformation (), allocator)) { + } + return result; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::shared_bind (const ACE_WString &name, + const ACE_WString &value, + const char *type, + int rebind) +{ + ACE_TRACE ("ACE_Local_Name_Space::shared_bind"); + size_t name_len = (name.length () + 1) * sizeof (ACE_USHORT16); + size_t value_len = (value.length () + 1) * sizeof (ACE_USHORT16); + size_t type_len = ACE_OS::strlen (type) + 1; + size_t total_len = name_len + value_len + type_len; + char *ptr = (char *) this->allocator_->malloc (total_len); + + if (ptr == 0) + return -1; + else + { + // Note that the value_rep *must* come first to make sure we can + // retrieve this pointer later on in unbind(). + ACE_USHORT16 *value_rep = (ACE_USHORT16 *) (ptr); + ACE_USHORT16 *name_rep = (ACE_USHORT16 *) (ptr + value_len); + char *new_type = (char *) (ptr + value_len + name_len); + ACE_NS_String new_name (name_rep, name.fast_rep (), name_len); + ACE_NS_String new_value (value_rep, value.fast_rep (), value_len); + ACE_OS::strcpy (new_type, type); + ACE_NS_Internal new_internal (new_value, new_type); + int result = -1; + + if (rebind == 0) + { + // Do a normal bind. This will fail if there's already an + // <new_internal> with the same name. + result = this->name_space_map_->bind (new_name, new_internal, this->allocator_); + + if (result == 1) + { + // Entry already existed so bind failed. Free our dynamically allocated memory. + this->allocator_->free ((void *) ptr); + return result; + } + } + else + { + // Do a rebind. If there's already any entry, this will return the existing + // <new_name> and <new_internal> and overwrite the existing name binding. + ACE_NS_String old_name; + ACE_NS_Internal old_internal; + + result = this->name_space_map_->rebind (new_name, new_internal, + old_name, old_internal, + this->allocator_); + if (result == 1) + { + // Free up the memory we allocated in shared_bind(). Note that this + // assumes that the "value" pointer comes first and that the value, + // name, and type are contiguously allocated (see above for details) + this->allocator_->free ((void *) (old_internal.value ()).fast_rep ()); + } + } + + if (result == -1) + // Free our dynamically allocated memory. + this->allocator_->free ((void *) ptr); + else + // If bind() or rebind() succeed, they will automatically sync + // up the map manager entry. However, we must sync up our + // name/value memory. + this->allocator_->sync (ptr, total_len); + + return result; + } +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::unbind (const ACE_WString &name) +{ + ACE_TRACE ("ACE_Local_Name_Space::unbind"); + + ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_NS_String ns_name (name); + ACE_NS_Internal ns_internal; + if (this->name_space_map_->unbind (ns_name, ns_internal, this->allocator_) != 0) + return -1; + else + { + // Free up the memory we allocated in shared_bind(). Note that + // this assumes that the "value" pointer comes first and that + // the value, name and type are contiguously allocated (see + // shared_bind() for details) + this->allocator_->free ((void *) (ns_internal.value ()).fast_rep ()); + return 0; + } +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::bind (const ACE_WString &name, + const ACE_WString &value, + const char *type) +{ + ACE_TRACE ("ACE_Local_Name_Space::bind"); + ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + return this->shared_bind (name, value, type, 0); +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::rebind (const ACE_WString &name, + const ACE_WString &value, + const char *type) +{ + ACE_TRACE ("ACE_Local_Name_Space::rebind"); + ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + return this->shared_bind (name, value, type, 1); +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::resolve (const ACE_WString &name, + ACE_WString &value, + char *&type) +{ + ACE_TRACE ("ACE_Local_Name_Space::resolve"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + ACE_NS_String ns_name (name); + ACE_NS_Internal ns_internal; + ACE_NS_String nbc_string; // Note the classy variable name! :) + int result = -1; + if (this->name_space_map_->find (ns_name, ns_internal, this->allocator_) != 0) + return -1; + else + { + // Calls conversion operator and then calls the ACE_WString + // assignment operator to get a fresh copy. (*#*(@#&!*@!!*@&( + // HP compiler causes us to add an extra copy explicitly !! :) + nbc_string = ns_internal.value (); + value = nbc_string; + + // Gets type and then the actual reprsentation which is a ACE_USHORT16 + const char *temp = ns_internal.type (); + + size_t len = ACE_OS::strlen (ns_internal.type ()); + // Makes a copy here. Caller needs to call delete to free up memory + char *new_type; + ACE_NEW_RETURN (new_type, char [len + 1], -1); + ACE_OS::strncpy (new_type, temp, len); + new_type[len] = '\0'; // Null terminate the string + type = new_type; + + return 0; + } +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::open (ACE_Naming_Context::Context_Scope_Type scope_in) +{ + ACE_TRACE ("ACE_Local_Name_Space::open"); + this->ns_scope_ = scope_in; + + return this->create_manager (); +} + +template <class MEM_POOL, class LOCK> +ACE_Local_Name_Space<MEM_POOL, LOCK>::ACE_Local_Name_Space (void) + : name_space_map_ (0), + name_options_ (0), + allocator_ (0) +{ + ACE_TRACE ("ACE_Local_Name_Space::ACE_Local_Name_Space"); +} + +template <class MEM_POOL, class LOCK> +ACE_Local_Name_Space<MEM_POOL, LOCK>::ACE_Local_Name_Space (ACE_Naming_Context::Context_Scope_Type scope_in, + ACE_Name_Options *name_options) + : name_options_ (name_options) +{ + ACE_TRACE ("ACE_Local_Name_Space::ACE_Local_Name_Space"); + if (this->open (scope_in) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Local_Name_Space::ACE_Local_Name_Space")); +} + +template <class MEM_POOL, class LOCK> +ACE_Local_Name_Space<MEM_POOL, LOCK>::~ACE_Local_Name_Space (void) +{ + ACE_TRACE ("ACE_Local_Name_Space::~ACE_Local_Name_Space"); + + // Remove the map + delete this->allocator_; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::create_manager (void) +{ + ACE_TRACE ("ACE_Local_Name_Space::create_manager"); + // Get directory name + const char *dir = this->name_options_->namespace_dir (); + + // Use process name as the file name. + size_t len = ACE_OS::strlen (dir); + len += ACE_OS::strlen (this->name_options_->database ()) + 1; + + if (len >= MAXNAMELEN) + { + errno = ENAMETOOLONG; + return -1; + } + + ACE_OS::strcpy (this->context_file_, dir); + ACE_OS::strcat (this->context_file_, ACE_DIRECTORY_SEPARATOR_STR); + ACE_OS::strcat (this->context_file_, this->name_options_->database ()); + + ACE_DEBUG ((LM_DEBUG, "contextfile is %s\n", + this->context_file_)); + + ACE_NEW_RETURN (this->allocator_, ALLOCATOR (this->context_file_), -1); + + // Now check if the backing store has been created successfully + if (ACE_OS::access (this->context_file_, F_OK) != 0) + ACE_ERROR_RETURN ((LM_ERROR, "create_manager\n"), -1); + + void *ns_map = 0; + + // This is the easy case since if we find the Name Server Map + // Manager we know it's already initialized. + if (this->allocator_->find (ACE_NAME_SERVER_MAP, ns_map) == 0) + { + this->name_space_map_ = (ACE_Name_Space_Map <ALLOCATOR> *) ns_map; + ACE_DEBUG ((LM_DEBUG, "name_space_map_ = %d, ns_map = %d\n", + this->name_space_map_, ns_map)); + } + + // This is the hard part since we have to avoid potential race + // conditions... + else + { + size_t map_size = sizeof *this->name_space_map_; + ns_map = this->allocator_->malloc (map_size); + + // Initialize the map into its memory location (e.g., shared memory). + ACE_NEW_RETURN (this->name_space_map_, + (ns_map) ACE_Name_Space_Map <ALLOCATOR> (this->allocator_), + -1); + + // Don't allow duplicates (atomically return existing int_id, if + // there is one). + if (this->allocator_->trybind (ACE_NAME_SERVER_MAP, ns_map) == 1) + { + // We're not the first one in, so free up the map and assign + // the map to the pointer that was allocated by the caller + // that was the first time in! + this->name_space_map_->close (this->allocator_); + + // Note that we can't free <map> since that was overwritten + // in the call to bind()! + this->allocator_->free ((void *) this->name_space_map_); + this->name_space_map_ = (ACE_Name_Space_Map <ALLOCATOR> *) ns_map; + } + ACE_DEBUG ((LM_DEBUG, "name_space_map_ = %d, ns_map = %d\n", + this->name_space_map_, ns_map)); + } + + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::list_names (ACE_PWSTRING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Local_Name_Space::list_names"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + int result = 1; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance()) + { + if (map_entry->ext_id_.strstr (pattern) != -1) + { + ACE_WString entry (map_entry->ext_id_ ); + + if (set.insert (entry) == -1) + { + result = -1; + break; + } + else + result = 0; + } + } + + return result; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::list_values (ACE_PWSTRING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Local_Name_Space::list_values"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + int result = 1; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance ()) + { + if (map_entry->int_id_.value ().strstr (pattern) != -1) + { + ACE_WString entry (map_entry->int_id_.value ()); + + if (set.insert (entry) == -1) + { + result = -1; + break; + } + else + result = 0; + } + } + + return result; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::list_types (ACE_PWSTRING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Local_Name_Space::list_types"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + char *compiled_regexp = 0; + + // Note that char_rep() allocates memory so we need to delete it + char *pattern_rep = pattern.char_rep (); + + // Check for wildcard case first. + if (ACE_OS::strcmp ("", pattern_rep) == 0) + compiled_regexp = ACE_OS::strdup (""); + else + // Compile the regular expression (the 0's cause ACE_OS::compile to allocate space). +#if defined (ACE_HAS_REGEX) + compiled_regexp = ACE_OS::compile (pattern_rep, 0, 0); +#else // If we don't have regular expressions just the pattern directly. + compiled_regexp = pattern_rep; +#endif /* ACE_HAS_REGEX */ + + int result = 1; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance ()) + { + // Get the type + const char *type = map_entry->int_id_.type (); + + if (ACE_OS::strcmp ("", pattern_rep) == 0 // Everything matches the wildcard. +#if defined (ACE_HAS_REGEX) + || ACE_OS::step (type, compiled_regexp) != 0) +#else // If we don't have regular expressions just use strstr() for substring matching. + || ACE_OS::strstr (type, compiled_regexp) != 0) +#endif /* ACE_HAS_REGEX */ + + { + ACE_WString entry (type); + + if (set.insert (entry) == -1) + { + result = -1; + break; + } + else + result = 0; + } + } +#if defined (ACE_HAS_REGEX) + if (compiled_regexp) + ACE_OS::free ((void *) compiled_regexp); +#endif /* ACE_HAS_REGEX */ + delete [] pattern_rep; // delete pattern_rep; + return result; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space <MEM_POOL, LOCK>::list_name_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Local_Name_Space::list_name_entries"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance()) + { + if (map_entry->ext_id_.strstr (pattern) != -1) + { + ACE_Name_Binding entry (map_entry->ext_id_, + map_entry->int_id_.value (), + map_entry->int_id_.type ()); + + if (set.insert (entry) == -1) + return -1; + } + } + + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::list_value_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Local_Name_Space::list_value_entries"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance ()) + { + if (map_entry->int_id_.value ().strstr (pattern) != -1) + { + ACE_Name_Binding entry (map_entry->ext_id_, + map_entry->int_id_.value (), + map_entry->int_id_.type ()); + + if (set.insert (entry) == -1) + return -1; + } + } + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Local_Name_Space<MEM_POOL, LOCK>::list_type_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Local_Name_Space::list_type_entries"); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + char *compiled_regexp = 0; + // Note that char_rep() allocates memory so we need to delete it + char *pattern_rep = pattern.char_rep (); + + // Check for wildcard case first. + if (ACE_OS::strcmp ("", pattern_rep) == 0) + compiled_regexp = ACE_OS::strdup (""); + else + // Compile the regular expression (the 0's cause ACE_OS::compile to allocate space). +#if defined (ACE_HAS_REGEX) + compiled_regexp = ACE_OS::compile (pattern_rep, 0, 0); +#else // If we don't have regular expressions just the pattern directly. + compiled_regexp = pattern_rep; +#endif /* ACE_HAS_REGEX */ + + int result = 1; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance ()) + { + // Get the type. + const char *type = map_entry->int_id_.type (); + + if (ACE_OS::strcmp ("", pattern_rep) == 0 // Everything matches the wildcard. +#if defined (ACE_HAS_REGEX) + || ACE_OS::step (type, compiled_regexp) != 0) +#else // If we don't have regular expressions just use strstr() for substring matching. + || ACE_OS::strstr (type, compiled_regexp) != 0) +#endif /* ACE_HAS_REGEX */ + { + ACE_Name_Binding entry (map_entry->ext_id_, + map_entry->int_id_.value (), + map_entry->int_id_.type ()); + + if (set.insert (entry) == -1) + return -1; + } + } +#if defined (ACE_HAS_REGEX) + if (compiled_regexp) + ACE_OS::free ((void *) compiled_regexp); +#endif /* ACE_HAS_REGEX */ + delete [] pattern_rep; // delete pattern_rep; + return 0; +} + + +template <class MEM_POOL, class LOCK> void +ACE_Local_Name_Space<MEM_POOL, LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Local_Name_Space::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + MAP_ITERATOR map_iterator (*this->name_space_map_); + MAP_ENTRY *map_entry; + + for (map_entry = 0; + map_iterator.next (map_entry) != 0; + map_iterator.advance()) + { + char *key = map_entry->ext_id_.char_rep (); + char *value = map_entry->int_id_.value ().char_rep (); + const char *type = map_entry->int_id_.type (); + + ACE_DEBUG ((LM_DEBUG, "key=%s\nvalue=%s\ntype=%s\n", + key, value, type)); + // We need to delete key and value since char_rep allocates memory for them + delete [] key; + delete [] value; + } + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#endif /* ACE_LOCAL_NAME_SPACE_T_C */ diff --git a/ace/Local_Name_Space_T.h b/ace/Local_Name_Space_T.h new file mode 100644 index 00000000000..ada018f91c7 --- /dev/null +++ b/ace/Local_Name_Space_T.h @@ -0,0 +1,219 @@ +/* -*- C++ -*- */ +// $Id$ + +/*-*- C++ -*- */ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Local_Name_Space_T.h +// +// = AUTHOR +// Prashant Jain (pjain@cs.wustl.edu), Irfan Pyarali +// (irfan@wuerl.wustl.edu), and Douglas C. Schmidt +// (schmidt@cs.wustl.edu). +// +// ============================================================================ + +#if !defined (ACE_LOCAL_NAME_SPACE_T_H) +#define ACE_LOCAL_NAME_SPACE_T_H + +#include "ace/Name_Space.h" +#include "ace/Naming_Context.h" +#include "ace/SString.h" +#include "ace/Local_Name_Space.h" + +// A short-hand name for our set of name/value/type tuples passed back +// to callers. +typedef ACE_Unbounded_Set<ACE_WString> ACE_WSTRING_SET; + +// Simplify later usage by defining typedefs. +typedef ACE_Map_Manager<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_MANAGER; +typedef ACE_Map_Iterator<ACE_NS_String, ACE_NS_Internal, ACE_Null_Mutex> MAP_ITERATOR; +typedef ACE_Map_Entry <ACE_NS_String, ACE_NS_Internal> MAP_ENTRY; + +template <class ALLOCATOR> +class ACE_Name_Space_Map : public MAP_MANAGER +{ + // = TITLE + // This class serves as a Proxy that ensures our process always + // has the appropriate allocator in place for every operation + // that accesses or updates the Map Manager. + // + // = DESCRIPTION + // We need this class because otherwise the SHARED_MALLOC + // pointer will be stored in the Map_Manager that resides within + // shared memory. Naturally, this will cause horrible problems + // since only the first process to set that pointer will be + // guaranteed the address of the SHARED_MALLOC allocator is + // meaningful! +public: + ACE_Name_Space_Map (ALLOCATOR *allocator); + // Constructor. + + // = The following methods are Proxies to the underlying methods + // provided by <ACE_Map_Manager>. When they are called, they + // acquire the lock, set the allocator to the one specific to this + // process, and then call down to perform the intended operation. + int bind (const ACE_NS_String &, + const ACE_NS_Internal &, + ALLOCATOR *allocator); + + int unbind (const ACE_NS_String &, + ACE_NS_Internal &, + ALLOCATOR *allocator); + + int rebind (const ACE_NS_String &, + const ACE_NS_Internal &, + ACE_NS_String &, + ACE_NS_Internal &, + ALLOCATOR *allocator); + + int find (const ACE_NS_String &, + ACE_NS_Internal &, + ALLOCATOR *allocator); + + int close (ALLOCATOR* allocator); + +private: +#if defined (ACE_WIN32) + int remap (EXCEPTION_POINTERS *ep, ALLOCATOR *allocator); + // Remap the backing store +#endif /* ACE_WIN32 */ +}; + +template <class MEM_POOL, class LOCK> +class ACE_Local_Name_Space : public ACE_Name_Space + // = TITLE + // Maintaining accesses Local Name Server Database. Allows to + // add NameBindings, change them, remove them and resolve + // NameBindings. + // + // = DESCRIPTION + // Manages a Naming Service for a local name space which includes + // bindings for node_local and host_local naming contexts. + // All strings are stored in wide character format. + // A Name Binding consists of a name (that's the key), a value + // string and an optional type string (no wide chars). +{ +public: + // = Initialization and termination methods. + ACE_Local_Name_Space (void); + // "Do-nothing" constructor. + + ACE_Local_Name_Space (ACE_Naming_Context::Context_Scope_Type scope_in, + ACE_Name_Options *name_options); + // Specifies the scope of this namespace, opens and memory-maps the + // associated file (if accessible) or contacts the dedicated name + // server process for NET_LOCAL namespace. + + int open (ACE_Naming_Context::Context_Scope_Type scope_in); + // Specifies the scope of this namespace, opens and memory-maps the + // associated file (if accessible) or contacts the dedicated name + // server process for NET_LOCAL namespace. + + ~ACE_Local_Name_Space (void); + // destructor, do some cleanup :TBD: last dtor should "compress" + // file + + virtual int bind (const ACE_WString &name, + const ACE_WString &value, + const char *type = ""); + // Bind a new name to a naming context (Wide character strings). + + virtual int rebind (const ACE_WString &name, + const ACE_WString &value, + const char *type = ""); + // Overwrite the value or type of an existing name in a + // ACE_Local_Name_Space or bind a new name to the context, if it + // didn't exist yet. (Wide charcter strings interface). + + virtual int unbind (const ACE_WString &name); + // Delete a name from a ACE_Local_Name_Space (Wide charcter strings + // Interface). + + virtual int resolve (const ACE_WString &name, + ACE_WString &value, + char *&type); + // Get value and type of a given name binding (Wide chars). The + // caller is responsible for deleting <type>! + + virtual int list_names (ACE_WSTRING_SET &set, + const ACE_WString &pattern); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. + + virtual int list_values (ACE_WSTRING_SET &set, + const ACE_WString &pattern); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. + + virtual int list_types (ACE_WSTRING_SET &set, + const ACE_WString &pattern); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. + + virtual int list_name_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_value_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_type_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual void dump (void) const; + // Dump the state of the object + +private: + int shared_bind (const ACE_WString &name, const ACE_WString &value, + const char *type, int rebind); + // Factor out code from bind() and rebind(). + + int create_manager (void); + // Allocate the appropriate type of map manager that stores the + // key/value binding. + + // = I just know this is going to cause problems on some platform... + typedef ACE_Allocator_Adapter <ACE_Malloc <MEM_POOL, LOCK> > ALLOCATOR; + + ALLOCATOR *allocator_; + // Pointer to the allocator + + ACE_Name_Space_Map <ALLOCATOR>*name_space_map_; + // Pointer to the allocated map manager. + + ACE_Naming_Context::Context_Scope_Type ns_scope_; + // Scope of this naming context (e.g., PROC_LOCAL, NODE_LOCAL, or NET_LOCAL). + + ACE_Name_Options *name_options_; + // Keep track of the options such as database name etc + + char context_file_[MAXNAMELEN]; + // Name of the file used as the backing store. + + LOCK lock_; + // Synchronization variable. +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Local_Name_Space_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Local_Name_Space_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_LOCAL_NAME_SPACE_T_H */ diff --git a/ace/Local_Tokens.cpp b/ace/Local_Tokens.cpp new file mode 100644 index 00000000000..9b39c22f451 --- /dev/null +++ b/ace/Local_Tokens.cpp @@ -0,0 +1,1408 @@ +// Local_Tokens.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Thread.h" +#include "ace/Local_Tokens.h" +#include "ace/Token_Manager.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Local_Tokens.i" +#endif /* __ACE_INLINE__ */ + +void +ACE_Tokens::dump (void) const +{ + ACE_TRACE ("ACE_Tokens::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Tokens::dump:\n" + " reference_cont_ = %d\n" + " token_name_ = %s\n", + reference_count_, token_name_)); + ACE_DEBUG ((LM_DEBUG, "waiters_\n")); + this->waiters_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Tokens::ACE_Tokens (void) + : reference_count_ (0), + visited_ (0) +{ + ACE_TRACE ("ACE_Tokens::ACE_Tokens"); +} + +void +ACE_Tokens::make_owner (ACE_TPQ_Entry *caller) +{ + this->waiters_.remove (caller); + this->waiters_.enqueue (caller, 0); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + + +void +ACE_TPQ_Entry::dump (void) const +{ + ACE_TRACE ("ACE_TPQ_Entry::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, + "ACE_TPQ_Entry::dump:\n" + " nesting_level_ = %d\n" + " client_id_ = %s\n", + nesting_level_, + client_id_)); + + if (next_ != 0) + { + ACE_DEBUG ((LM_DEBUG, "next:.\n")); + next_->dump (); + } + + ACE_DEBUG ((LM_DEBUG, "ACE_TPQ_Entry::dump end.\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_TPQ_Entry::ACE_TPQ_Entry (const ACE_Token_Proxy *new_proxy, + const char *client_id) + : cond_var_ (lock_), + // This const typecast is safe. + proxy_ ((ACE_Token_Proxy *) new_proxy), + nesting_level_ (0), + sleep_hook_ (0), + next_ (0) +{ + ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry"); + + if (client_id != 0) + this->client_id (client_id); + else + { + // Just make sure we have enough space. + char host_name[MAXHOSTNAMELEN]; + char name[sizeof host_name + 256]; + ACE_OS::hostname (host_name, sizeof host_name); + + ACE_OS::sprintf (name, + "/%s/%u/%u", + host_name, + ACE_OS::getpid (), + ACE_Thread::self ()); + + this->client_id (name); + } +} + +ACE_TPQ_Entry::ACE_TPQ_Entry (void) + : proxy_ (0), + nesting_level_ (0), + sleep_hook_ (0), + cond_var_ (lock_) +{ + ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry null const."); +} + +ACE_TPQ_Entry::ACE_TPQ_Entry (const ACE_TPQ_Entry &rhs) +: cond_var_ (lock_) +{ + ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry copy const."); + *this = rhs; +} + +ACE_TPQ_Entry::~ACE_TPQ_Entry (void) +{ + ACE_TRACE ("ACE_TPQ_Entry::~ACE_TPQ_Entry"); +} + +void +ACE_TPQ_Entry::operator= (const ACE_TPQ_Entry& rhs) +{ + ACE_TRACE ("ACE_TPQ_Entry::operator="); + if (&rhs == this) + return; + this->proxy_ = rhs.proxy (); + this->nesting_level_ = rhs.nesting_level (); + this->client_id (rhs.client_id ()); + this->sleep_hook_ = rhs.sleep_hook (); +} + +void +ACE_TPQ_Entry::client_id (const char *id) +{ + ACE_TRACE ("ACE_TPQ_Entry::client_id"); + + if (id == 0) + return; + + int n = ACE_OS::strlen (id) + 1; + + if (n >= ACE_MAXCLIENTIDLEN) + n = ACE_MAXCLIENTIDLEN - 1; + + ACE_OS::strncpy (this->client_id_, (char *) id, n); + this->client_id_[ACE_MAXCLIENTIDLEN - 1] = '\0'; +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_TSS_TPQ_Entry::dump (void) const +{ + ACE_TRACE ("ACE_TSS_TPQ_Entry::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_TSS_TPQ_Entry::dump:\n" + " client_id_ = %s\n", + client_id_ == 0 ? "0" : client_id_)); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_TSS<ACE_TPQ_Entry>::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_TSS_TPQ_Entry::ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy, + const char *client_id) +: proxy_ (proxy), + client_id_ (client_id) +{ + ACE_TRACE ("ACE_TSS_TPQ_Entry::ACE_TSS_TPQ_Entry"); +} + +ACE_TPQ_Entry * +ACE_TSS_TPQ_Entry::make_TSS_TYPE (void) const +{ + ACE_TRACE ("ACE_TSS_TPQ_Entry::make_TSS_TYPE"); + ACE_TPQ_Entry *temp; + + ACE_NEW_RETURN (temp, ACE_TPQ_Entry (this->proxy_, this->client_id_), 0); + return temp; +} + +ACE_TSS_TPQ_Entry::operator ACE_TPQ_Entry * (void) +{ + ACE_TRACE ("ACE_TSS_TPQ_Entry::operator"); + return (ACE_TPQ_Entry *) (*((ACE_TSS<ACE_TPQ_Entry> *) this)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +ACE_TPQ_Iterator::ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q) +: current_ (q.head_) +{ + ACE_TRACE ("ACE_TPQ_Iterator::ACE_TPQ_Iterator"); +} + +int +ACE_TPQ_Iterator::next (ACE_TPQ_Entry *&next_item) +{ + ACE_TRACE ("ACE_TPQ_Iterator::next"); + + next_item = current_; + + if (current_ == 0) + return 0; + + return 1; +} + +void +ACE_TPQ_Iterator::advance (void) +{ + ACE_TRACE ("ACE_TPQ_Iterator::advance"); + if (current_ != 0) + current_ = current_->next_; +} + +void +ACE_TPQ_Iterator::dump (void) const +{ + ACE_TRACE ("ACE_TPQ_Iterator::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_TPQ_Iterator::dump:\n" + " current_ = %d\n", + (long) current_)); + ACE_DEBUG ((LM_DEBUG, "head_ and tail_\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_Token_Proxy_Queue::dump (void) const +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Proxy_Queue::dump:\n" + " size_ = %d\n", + size_)); + ACE_DEBUG ((LM_DEBUG, "head_ and tail_\n")); + if (this->head_ != 0) + this->head_->dump (); + + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Proxy_Queue::dump end.\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Token_Proxy_Queue::ACE_Token_Proxy_Queue (void) + : head_ (0), + tail_ (0), + size_ (0) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::ACE_Token_Proxy_Queue"); +} + +void +ACE_Token_Proxy_Queue::enqueue (ACE_TPQ_Entry *tpq, + int position) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::enqueue"); + tpq->next_ = 0; + + ++this->size_; + + if (this->head_ == 0) + { + // make tpq the entire list + this->head_ = this->tail_ = tpq; + return; + } + + if (position == 0) + { + // make head of list + tpq->next_ = this->head_; + this->head_ = tpq; + return; + } + + if (position == -1) + { + // stick at back of list + this->tail_->next_ = tpq; + this->tail_ = tpq; + return; + } + + // walk through list to insertion point + ACE_TPQ_Entry *temp = head_; + + for (int x = position; x > 1; --x) + { + // end of queue? + if (temp->next_ == 0) + break; + // advance pointer + else + temp = temp->next_; + } + + // insert new tpq after temp + tpq->next_ = temp->next_; + temp->next_ = tpq; +} + +void +ACE_Token_Proxy_Queue::dequeue (void) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::dequeue"); + + if (head_ == 0) + return; + + ACE_TPQ_Entry *temp = this->head_; + + this->head_ = this->head_->next_; + + temp->next_ = 0; + + --this->size_; + + if (this->head_ == 0 && this->size_ != 0) + ACE_ERROR ((LM_ERROR, "incorrect size = %d\n", this->size_)); +} + +/* +int +ACE_Token_Proxy_Queue::member (const char *id) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::member"); + + for (ACE_TPQ_Entry *temp = this->head_; temp != 0; temp = temp->next_) + if (ACE_OS::strcmp (temp->client_id (), id) == 0) + // We found it! + return 1; + + // We didn't find it :-( + return 0; +} +*/ + +void +ACE_Token_Proxy_Queue::remove (const ACE_TPQ_Entry *remove_me) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::remove"); + // sanity + if ((remove_me == 0) || (this->head_ == 0)) + return; + + // is it the head? + if (this->head_ == remove_me) // pointer comparison. + { + this->head_ = this->head_->next_; + if (this->head_ == 0) + this->tail_ = 0; + + --this->size_; + return; + } + + ACE_TPQ_Entry *temp = this->head_; + ACE_TPQ_Entry *previous = 0; + + // is it in the middle or tail? + while (temp != 0) + { + if (temp == remove_me) + { + // previous should never be null since the first if + // conditional should always be false + previous->next_ = temp->next_; + // is it the tail? + if (this->tail_ == temp) + this->tail_ = previous; + + --this->size_; + return; + } + + previous = temp; + temp = temp->next_; + } + + // it wasn't in the list. + return; +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_Mutex_Token::dump (void) const +{ + ACE_TRACE ("ACE_Mutex_Token::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Mutex_Token::dump:\n")); + ACE_DEBUG ((LM_DEBUG, "lock_\n")); + lock_.dump (); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Tokens::dump (); + ACE_DEBUG ((LM_DEBUG, "ACE_Mutex_Token::dump end.\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Mutex_Token::ACE_Mutex_Token (const char *name) +{ + ACE_TRACE ("ACE_Mutex_Token::ACE_Mutex_Token"); + + int n = ACE_OS::strlen (name) + 1; // + 1 for \0 + + if (n > ACE_MAXTOKENNAMELEN) + n = ACE_MAXTOKENNAMELEN - 1; + + ACE_OS::strncpy (this->token_name_, name, n); + this->token_name_[ACE_MAXTOKENNAMELEN - 1] = '\0'; +} + +ACE_Mutex_Token::~ACE_Mutex_Token (void) +{ + ACE_TRACE ("ACE_Mutex_Token::~ACE_Mutex_Token"); +} + +int +ACE_Mutex_Token::acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify) +{ + ACE_TRACE ("ACE_Mutex_Token::acquire"); + // We need to acquire two locks. This one to ensure that only one + // thread uses this token at a time. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1); + // This one to ensure an atomic transaction across all tokens. Note + // that this order is crucial too. It's resource coloring for other + // threads which may be calling this same token. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1); + + // Does _anyone_ own the token? + if (this->owner () == 0) + { + // there are no waiters, so queue as the first waiter (the owner.) + this->waiters_.enqueue (caller, -1); + return 0; // success + } + + // Does the caller already own it? + if (this->is_owner (caller->client_id ())) + { + // Recursive acquisition. + caller->nesting_level (1); + return 0; // success + } + + // Check for deadlock. + if (!ignore_deadlock + && ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1) + { + errno = EDEADLK; + ACE_RETURN (-1); + } + + // Someone owns it. Sorry, you're getting queued up at the end of + // the waiter queue. + this->waiters_.enqueue (caller, -1); + + if (notify) + this->owner ()->call_sleep_hook (); + + errno = EWOULDBLOCK; + ACE_RETURN (-1); +} + +int +ACE_Mutex_Token::tryacquire (ACE_TPQ_Entry *caller) +{ + ACE_TRACE ("ACE_Mutex_Token::tryacquire"); + // We need to acquire two locks. This one to ensure that only one + // thread uses this token at a time. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1); + // This one to ensure an atomic transaction across all tokens. Note + // that this order is crucial too. It's resource coloring for other + // threads which may be calling this same token. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1); + + // Does _anyone_ own the token? + if (this->owner () == 0) + { + this->waiters_.enqueue (caller, -1); + return 0; // success + } + // Does the caller already own it? + if (this->is_owner (caller->client_id ())) + { + // recursive acquisition + caller->nesting_level (1); + return 0; // success + } + else + // Someone owns it. Fail. + { + errno = EWOULDBLOCK; + ACE_RETURN (-1); + } +} + +int +ACE_Mutex_Token::renew (ACE_TPQ_Entry *caller, + int requeue_position) +{ + ACE_TRACE ("ACE_Mutex_Token::renew"); + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + // Verify that the caller is the owner. + if (this->is_owner (caller->client_id ()) == 0) + { + errno = EACCES; + ACE_RETURN (-1); + } + + // The caller is the owner, so check to see if there are any + // waiters. If not, we just keep the token. == 1 means that there + // is only the owner. + if (this->waiters_.size () == 1 || requeue_position == 0) + return 0; + + // Requeue the caller. + this->waiters_.dequeue (); + + this->waiters_.enqueue (caller, requeue_position); + + // Notify new owner. + if (this->owner () != 0) + this->owner ()->proxy ()->token_acquired (this->owner ()); + + // Tell the caller that the operation would block. + errno = EWOULDBLOCK; + ACE_RETURN (-1); +} + +// Release the current holder of the token (which had +// better be the caller's thread!). + +int +ACE_Mutex_Token::release (ACE_TPQ_Entry *caller) +{ + ACE_TRACE ("ACE_Mutex_Token::release"); + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + // Does anyone own the token? + if (this->owner () == 0) + { + errno = EACCES; + ACE_RETURN (-1); + } + + // Is the caller the owner. + if (this->is_owner (caller->client_id ())) + { + // Check the nesting level. + if (caller->nesting_level () > 0) + caller->nesting_level (-1); + else + { + this->waiters_.dequeue (); + // Notify new owner. + if (this->owner () != 0) + this->owner ()->proxy ()->token_acquired (this->owner ()); + } + } + else + this->remove (caller); + + return 0; +} + +int +ACE_Mutex_Token::owners (OWNER_STACK &stack, + const char *id) +{ + ACE_TRACE ("ACE_Mutex_Token::owners"); + if (this->owner () != 0) + { + stack.push (this->owner ()); + // If an <id> is specified, return whether it is the owner being + // returned. + if (id != 0) + return this->owner ()->equal_client_id (id); + } + + return 0; +} + +int +ACE_Mutex_Token::is_waiting_for (const char *id) +{ + ACE_TRACE ("ACE_Mutex_Token::is_waiting_for"); + // If there is no owner, or <id> is the owner, return false. + if ((this->owner () == 0) || this->is_owner (id)) + return 0; + + // Step through each waiter looking for <id>. + ACE_TPQ_Iterator iterator (waiters_); + iterator.advance (); + for (ACE_TPQ_Entry *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (temp->equal_client_id (id)) + return 1; + } + + return 0; +} + +int +ACE_Mutex_Token::is_owner (const char *id) +{ + ACE_TRACE ("ACE_Mutex_Token::is_owner"); + // If there is an owner, return whether it is <id>. + if ((this->owner () != 0) && + this->owner ()->equal_client_id (id)) + return 1; + else + return 0; +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_RW_Token::dump (void) const +{ + ACE_TRACE ("ACE_RW_Token::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_RW_Token::dump:\n" + "num_writers_ = %d\n", num_writers_)); + ACE_DEBUG ((LM_DEBUG, "lock_\n")); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Tokens::dump (); + ACE_DEBUG ((LM_DEBUG, "ACE_RW_Token::dump end.\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_RW_Token::ACE_RW_Token (const char *name) +: num_writers_ (0) +{ + ACE_TRACE ("ACE_RW_Token::ACE_RW_Token"); + + int n = ACE_OS::strlen (name) + 1; // + 1 for \0 + + if (n > ACE_MAXTOKENNAMELEN) + n = ACE_MAXTOKENNAMELEN; + + ACE_OS::strncpy (this->token_name_, name, n); + this->token_name_[ACE_MAXTOKENNAMELEN - 1] = '\0'; +} + +ACE_RW_Token::~ACE_RW_Token (void) +{ + ACE_TRACE ("ACE_RW_Token::~ACE_RW_Token"); +} + +int +ACE_RW_Token::acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify) +{ + ACE_TRACE ("ACE_RW_Token::acquire"); + // We need to acquire two locks. This one to ensure that only one + // thread uses this token at a time. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1); + // This one to ensure an atomic transaction across all tokens. Note + // that this order is crucial too. It's resource coloring for other + // threads which may be calling this same token. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1); + + if (caller->proxy ()->type () == ACE_RW_Token::WRITER) + this->num_writers_++; + + // Does _anyone_ own the token? + if (this->owner () == 0) + { + // There are no waiters, so queue as the first waiter (the owner). + this->waiters_.enqueue (caller, -1); + return 0; + } + + // Check for recursive acquisition. + if (this->is_owner (caller->client_id ())) + { + caller->nesting_level (1); + return 0; // Success. + } + + // Reader. + if (caller->proxy ()->type () == ACE_RW_Token::READER) + { + // Are there any writers? + if (this->num_writers_ == 0) + { + // Queue the caller at the end of the queue. + this->waiters_.enqueue (caller, -1); + return 0; + } + // Else failure. + } + + // Failure code. + + // Check for deadlock. + if (!ignore_deadlock && + ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1) + { + if (caller->proxy ()->type () == ACE_RW_Token::WRITER) + this->num_writers_--; + errno = EDEADLK; + ACE_RETURN (-1); + } + + // Queue the caller at the end of the queue. + this->waiters_.enqueue (caller, -1); + + if (notify) + { + // If it's a writer, just notify it. + if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER) + this->owner ()->call_sleep_hook (); + else + { + // Call back all reader owners. + ACE_TPQ_Entry *temp = this->owner (); + do + { + temp->call_sleep_hook (); + temp = temp->next_; + } + while (temp != 0 && + temp->proxy ()->type () == ACE_RW_Token::READER); + } + } + + errno = EWOULDBLOCK; + ACE_RETURN (-1); +} + + +int +ACE_RW_Token::tryacquire (ACE_TPQ_Entry *caller) +{ + ACE_TRACE ("ACE_RW_Token::tryacquire"); + // We need to acquire two locks. This one to ensure that only one + // thread uses this token at a time. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1); + // This one to ensure an atomic transaction across all tokens. Note + // that this order is crucial too. It's resource coloring for other + // threads which may be calling this same token. + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1); + + if (caller->proxy ()->type () == ACE_RW_Token::WRITER) + { + this->num_writers_++; + } + + // Does _anyone_ own the token? + if (this->owner () == 0) + { + // There are no waiters, so queue as the first waiter (the owner). + this->waiters_.enqueue (caller, -1); + return 0; + } + + // Check for recursive acquisition. + if (this->is_owner (caller->client_id ())) + { + caller->nesting_level (1); + return 0; // Success. + } + + // Reader. + if (caller->proxy ()->type () == ACE_RW_Token::READER) + { + // Are there any writers? + if (this->num_writers_ == 0) + { + // queue the caller at the end of the queue. + this->waiters_.enqueue (caller, -1); + return 0; + } + // Else, fail. + } + else // Writer. + // We're going to fail, so decrement the num_writers. + { + this->num_writers_--; + } + + + errno = EWOULDBLOCK; + ACE_RETURN (-1); +} + +int +ACE_RW_Token::renew (ACE_TPQ_Entry *caller, + int requeue_position) +{ + ACE_TRACE ("ACE_RW_Token::renew"); + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + // Werify that the caller is the owner + if (this->is_owner (caller->client_id ()) == 0) + { + errno = EACCES; + ACE_RETURN (-1); + } + + // The caller is the owner, so check to see if there are any + // waiters. If not, we just keep the token. + if (this->waiters_.size () == 1 || requeue_position == 0) + return 0; + + // There are waiters, so remove the caller. + this->remove (caller); + + // Requeue the caller. + this->waiters_.enqueue (caller, requeue_position); + + if (caller->proxy ()->type () == ACE_RW_Token::READER) + { + // If the caller got queued before any writers, the caller is + // still the owner. + if (this->is_owner (caller->client_id ())) + return 0; // success + // else fallthrough and return would block. + } + // Writers will always have to block since waiters_.size () == 1 or + // requeue_position == 0. + + // Get a new owner. + this->notify_new_owner (caller); + + // Tell the caller that the operation would block. + errno = EWOULDBLOCK; + ACE_RETURN (-1); +} + +int +ACE_RW_Token::release (ACE_TPQ_Entry *caller) +{ + ACE_TRACE ("ACE_RW_Token::release"); + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + // Check for errors. + if ((this->owner () == 0) || + (this->is_owner (caller->client_id ()) == 0)) + { + errno = EACCES; + ACE_RETURN (-1); + } + + if (caller->proxy ()->type () == ACE_RW_Token::WRITER) + num_writers_--; + + // Recursive release. + if (caller->nesting_level () > 0) + { + caller->nesting_level (-1); + return 0; + } + + // Remove the caller and notify the new owner(s). + this->remove (caller); + this->notify_new_owner (caller); + + return 0; +} + +void +ACE_RW_Token::notify_new_owner (ACE_TPQ_Entry *old_owner) +{ + ACE_TRACE ("ACE_RW_Token::new_owner"); + + if (this->owner () == 0) + return; + + if (this->owner ()->proxy ()->type () == ACE_RW_Token::READER) + { + if (old_owner->proxy ()->type () == ACE_RW_Token::READER) + // the owners already know that they're owners + return; + + // The current owner is a reader and the previous owner was a + // writer, so notify all waiting readers up to the first writer. + // call back all reader owners. + ACE_TPQ_Iterator iterator (waiters_); + for (ACE_TPQ_Entry *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (temp->proxy ()->type () == WRITER) + // We've gone through all the readers. + break; + + temp->proxy ()->token_acquired (temp); + } + } + else // writer + this->owner ()->proxy ()->token_acquired (this->owner ()); +} + + +int +ACE_RW_Token::owners (OWNER_STACK &stack, + const char *id) +{ + ACE_TRACE ("ACE_RW_Token::owners"); + + if (this->owner () == 0) + return 0; + + int id_is_owner = 0; + + // The first waiter is a writer, so there is only one owner. + if (this->owner ()->proxy ()->type () == WRITER) + { + stack.push (this->owner ()); + // If an <id> is specified, return whether it is the owner being + // returned. + if ((id != 0) && + (ACE_OS::strcmp (id, this->owner ()->client_id ()) == 0)) + id_is_owner = 1; + } + // The first waiter is a reader, so there can be multiple owning + // readers. + else + { + ACE_TPQ_Iterator iterator (waiters_); + for (ACE_TPQ_Entry *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (temp->proxy ()->type () == WRITER) + // We've gone through all the readers. + break; + + stack.push (temp); + + if (!id_is_owner && (id != 0) && + (ACE_OS::strcmp (id, temp->client_id ()) == 0)) + id_is_owner = 1; + } + } + + return id_is_owner; +} + +int +ACE_RW_Token::is_waiting_for (const char *id) +{ + ACE_TRACE ("ACE_RW_Token::is_waiting_for"); + // If there is no owner, or <id> is the owner, return false. + if ((this->owner () == 0) || + this->is_owner (id)) + return 0; + + // Step through each waiter looking for <id>. + ACE_TPQ_Iterator iterator (waiters_); + iterator.advance (); + for (ACE_TPQ_Entry *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (temp->equal_client_id (id)) + return 1; + } + + return 0; +} + +int +ACE_RW_Token::is_owner (const char *id) +{ + ACE_TRACE ("ACE_Mutex_Token::is_owner"); + // If there is no owner, return false. + if (this->owner () == 0) + return 0; + + // A writer owns us. + if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER) + return this->owner ()->equal_client_id (id); + + // Readers own us. + // Step through each owning reader looking for <id>. + ACE_TPQ_Iterator iterator (waiters_); + for (ACE_TPQ_Entry *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (temp->proxy ()->type () != ACE_RW_Token::READER) + break; + + if (temp->equal_client_id (id)) + return 1; + } + + return 0; +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ +// 7.. + +void +ACE_Token_Proxy::dump (void) const +{ + ACE_TRACE ("ACE_Token_Proxy::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Proxy::dump:\n" + " type = %d\n" + " ignore_deadlock_ = %d\n" + " debug_ = %d\n", + (int) this->type (), ignore_deadlock_, debug_)); + ACE_DEBUG ((LM_DEBUG, "mutex_, and waiter_\n")); + + if (this->token_ != 0) + this->token_->dump (); + + this->waiter_.dump (); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Proxy::dump end.\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +const char* +ACE_Token_Proxy::client_id (void) const +{ + ACE_TRACE ("ACE_Token_Proxy::client_id"); + // Thread-specific. + const char *id = this->waiter_->client_id (); + + if (id == 0) + return "ERROR NO CLIENT ID"; + else + return id; +} + +void +ACE_Token_Proxy::client_id (const char *client_id) +{ + ACE_TRACE ("ACE_Token_Proxy::client_id"); + this->waiter_->client_id (client_id); +} + +const char * +ACE_Token_Proxy::owner_id (void) +{ + ACE_TRACE ("ACE_Token_Proxy::owner_id"); + return this->token_->owner_id (); +} + +const char * +ACE_Token_Proxy::name (void) const +{ + ACE_TRACE ("ACE_Token_Proxy::owner_id"); + return this->token_->name (); +} + +ACE_Token_Proxy::ACE_Token_Proxy (void) +: token_ (0), + waiter_ (this, 0) +{ + ACE_TRACE ("ACE_Token_Proxy::ACE_Token_Proxy"); +} + +// Notice the token_ (0). Do *not* copy the token pointer. This must +// be obtained through the token manager. Also, we don't copy any +// waiter info. A copied Proxy does *not* inherit client_id. +ACE_Token_Proxy::ACE_Token_Proxy (const ACE_Token_Proxy &p) +: token_ (0), + waiter_ (this, 0) +{ + ACE_TRACE ("ACE_Token_Proxy::ACE_Token_Proxy"); +} + +// @@ should I do a mutex_->release ()? +ACE_Token_Proxy::~ACE_Token_Proxy (void) +{ + ACE_TRACE ("ACE_Local_Mutex::~ACE_Local_Mutex"); + + if (token_ != 0) + // notify token manager that we are done with it so it can + // free it if necessary + ACE_Token_Manager::instance ()->release_token (token_); +} + +int +ACE_Token_Proxy::open (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Token_Proxy::open"); + + // Store some parameters. + this->ignore_deadlock_ = ignore_deadlock; + this->debug_ = debug; + + // Used in case a name was not specified. + char name[BUFSIZ]; + + // We must have a name. + if (token_name == 0) + { + ACE_OS::sprintf (name, "token %d", this); + token_name = name; + } + + // Get or create the underlying token. The Token Manager will call + // us back to set token_. + ACE_Token_Manager::instance ()->get_token (this, token_name); + + // Check for failed get or failed new. + if (this->token_ == 0) + { + errno = ENOMEM; + ACE_ERROR_RETURN ((LM_ERROR, "Can't allocate mutex"), -1); + } + + return 0; +} + +int +ACE_Token_Proxy::acquire (int notify, + void (*sleep_hook)(void *), + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Proxy::acquire"); + if (this->token_ == 0) + { + errno = ENOENT; + ACE_ERROR_RETURN ((LM_ERROR, "Not open.\n"), -1); + } + + // Make sure no one calls our token_acquired until we have a chance + // to sleep first! If after we call an EWOULDBLOCK + // mutex_->acquire() below, but before we enter handle_options to + // wait on the cond_var, a thread tries to give take us off the + // waiter queue and signal us, IT WILL FIRST HAVE TO ACQUIRE THIS + // cond_var.mutex (). _This_ is why we acquire it. + this->waiter_->cond_var_.mutex ().acquire (); + + this->waiter_->sleep_hook (sleep_hook); + + if (this->token_->acquire (this->waiter_, this->ignore_deadlock_, notify) == -1) + // acquire failed + { + switch (errno) + { + case EDEADLK : + if (!ignore_deadlock_) + { + waiter_->cond_var_.mutex ().release (); + errno = EDEADLK; + ACE_RETURN (-1); + } + // Else, fallthrough and block! + + case EWOULDBLOCK : + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, + "(%t) waiting for %s, owner is %s, " + "total waiters == %d\n", + this->name (), + this->token_->owner_id (), + token_->no_of_waiters ())); + + // no error, but would block, + // if error, return error (-1), otherwise, return whether we + // called the holder or not. + int return_value; + if (this->handle_options (options, waiter_->cond_var_) == -1) + return_value = -1; + else + return_value = notify == 1; + + errno = EWOULDBLOCK; + ACE_RETURN (return_value); + + default : + waiter_->cond_var_.mutex ().release (); + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n","Token Proxy acquire."), -1); + } + } + else + // we have the token + { + if (debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) acquired %s\n", + this->name ())); + waiter_->cond_var_.mutex ().release (); + } + + return 0; +} + +int +ACE_Token_Proxy::tryacquire (void (*sleep_hook)(void *)) +{ + ACE_TRACE ("ACE_Token_Proxy::tryacquire"); + if (this->token_ == 0) + { + errno = ENOENT; + ACE_ERROR_RETURN ((LM_ERROR, "Not open.\n"), -1); + } + + this->waiter_->sleep_hook (sleep_hook); + + return this->token_->tryacquire (waiter_); +} + +int +ACE_Token_Proxy::renew (int requeue_position, + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Proxy::renew"); + if (this->token_ == 0) + { + errno = ENOENT; + ACE_ERROR_RETURN ((LM_ERROR, "Not open.\n"), -1); + } + + // Make sure no one calls our token_acquired until we have a chance + // to sleep first! + this->waiter_->cond_var_.mutex ().acquire (); + + if (this->token_->renew (this->waiter_, requeue_position) == -1) + { + // check for error + if (errno != EWOULDBLOCK) + ACE_ERROR_RETURN ((LM_ERROR, + "%p renew failed\n", "ACE_Token_Proxy"), -1); + + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) renew blocking for %s, owner is %s\n", + this->name (), + token_->owner_id ())); + + // no error, but would block, so block or return + return this->handle_options (options, waiter_->cond_var_); + } + else + // we have the token + { + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) renewed %s\n", + this->name ())); + waiter_->cond_var_.mutex ().release (); + return 0; + } +} + +int +ACE_Token_Proxy::handle_options (ACE_Synch_Options &options, + ACE_TOKEN_CONST::COND_VAR &cv) +{ + // Some operation failed with EWOULDBLOCK. + ACE_TRACE ("ACE_Token_Proxy::handle_options"); + + if (options[ACE_Synch_Options::USE_REACTOR] == 1) + // Asynchronous. + { + int error = errno; + // if (options[ACE_Synch_Options::USE_TIMEOUT] == 1) + // ACE_ERROR_RETURN ((LM_ERROR, "Timeouts not yet supported" " + // with asynchronous operations."), -1); + cv.mutex ().release (); + errno = error; + ACE_RETURN (-1); + } + else + // Synchronous. + { + // Block on condition variable. + while (cv.wait ((ACE_Time_Value *) options.time_value ()) == -1) + { + // Note, this should obey whatever thread-specific + // interrupt policy is currently in place... + if (errno == EINTR) + continue; + // We come here if a timeout occurs or some serious + // ACE_Condition object error. + cv.mutex ().release (); + ACE_ERROR_RETURN ((LM_ERROR, "condition variable wait" + " bombed."), -1); + } + + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) unblocking.\n", + this->client_id ())); + cv.mutex ().release (); + return 0; // operation succeeded + } +} + +int +ACE_Token_Proxy::release (ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Proxy::release"); + if (this->token_ == 0) + { + errno = ENOENT; + if (debug_) + ACE_DEBUG ((LM_DEBUG, "Must open before releasing.\n")); + ACE_RETURN (-1); + } + + if (this->token_->release (waiter_) != 0) + { + // Release failed. + this->token_->remove (this->waiter_); + if (debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) %p.\n", "release failed")); + return -1; + } + else + { + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) released %s, owner is %s\n", + this->name (), + token_->owner_id ())); + + return 0; + } +} + +int +ACE_Token_Proxy::remove (ACE_Synch_Options &) +{ + ACE_TRACE ("ACE_Token_Proxy::remove"); + return 0; +} + +void +ACE_Token_Proxy::sleep_hook (void) +{ + ACE_TRACE ("ACE_Token_Proxy::sleep_hook"); + // Somebody wants our token! (Let'em wait...) + return; +} + +void +ACE_Token_Proxy::token_acquired (ACE_TPQ_Entry *e) +{ + ACE_TRACE ("ACE_Token_Proxy::token_acquired"); + e->cond_var_.mutex ().acquire (); + // We've been taken off the waiters list and given the token! + // This implementation signals the internal condition + // variable. Thus, if asynchronous acquires are used, this must be + // overriden to do something more useful! + e->cond_var_.signal (); + e->cond_var_.mutex ().release (); + + return; +} + +// ************************************************************ + +ACE_Token_Name::ACE_Token_Name (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Name::ACE_Token_Name"); + this->name (token_name); +} + +ACE_Token_Name::ACE_Token_Name (const ACE_Token_Name &rhs) +{ + ACE_TRACE ("ACE_Token_Name::ACE_Token_Name"); + this->name (rhs.name ()); +} + +ACE_Token_Name::~ACE_Token_Name () +{ + ACE_TRACE ("ACE_Token_Name::~ACE_Token_Name"); +} + +void +ACE_Token_Name::dump (void) const +{ + ACE_TRACE ("ACE_Token_Name::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Name::dump:\n" + " token_name_ = %s\n", + token_name_ == 0 ? "no name" : token_name_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +#if !defined (ACE_NO_TSS_TOKENS) +template class ACE_TSS <ACE_TPQ_Entry>; +#endif /* ACE_NO_TSS_TOKENS */ +template class ACE_Unbounded_Stack <ACE_TPQ_Entry *>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Local_Tokens.h b/ace/Local_Tokens.h new file mode 100644 index 00000000000..6d5786f2658 --- /dev/null +++ b/ace/Local_Tokens.h @@ -0,0 +1,974 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Local_Tokens +// +// = AUTHOR +// Karl-Heinz Dorn (kdorn@erlh.siemens.de) +// Douglas C. Schmidt (schmidt@cs.wustl.edu) +// Tim Harrison (harrison@cs.wustl.edu) +// +// = DESCRIPTION +// This file contains definitions for the following classes: +// +// public: +// 7. ACE_Token_Proxy +// 8. ACE_Null_Token : public ACE_Token_Proxy +// 9. ACE_Local_Mutex : public ACE_Token_Proxy +// *. ACE_Local_RLock : public ACE_Local_Mutex +// &. ACE_Local_WLock : public ACE_Local_Mutex +// private: +// 1. ACE_TOKEN_CONST +// 3. ACE_TPQ_Entry +// b. ACE_TSS_TPQ_Entry +// c. ACE_TPQ_Iterator +// 4. ACE_Token_Proxy_Queue +// 5. ACE_Tokens +// 6. ACE_Mutex_Token : public ACE_Tokens +// 12. ACE_RW_Token : public ACE_Tokens +// a. ACE_Token_Name +// +// ============================================================================ + +#if !defined (ACE_LOCAL_MUTEX_H) +#define ACE_LOCAL_MUTEX_H + +#include "ace/Synch.h" +#include "ace/Stack.h" +#include "ace/Synch_Options.h" +#include "ace/Map_Manager.h" + +// 1. +class ACE_Export ACE_TOKEN_CONST +{ + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Constant definitions and typdefs for Token library. Mostly, + // this class is necessary to fight the compiler with order of + // declaration errors. +public: +#if defined (ACE_MT_SAFE) + // ACE platform supports some form of threading. + typedef ACE_Condition_Thread_Mutex COND_VAR; + typedef ACE_Thread_Mutex MUTEX; + typedef ACE_Thread_Mutex_Guard GUARD; +#else + typedef ACE_Null_Condition_Mutex COND_VAR; + typedef ACE_Null_Mutex MUTEX; + typedef ACE_Null_Mutex_Guard GUARD; +#endif /* ACE_HAS_THREADS */ +}; + +class ACE_Token_Proxy; + +// 3.. +class ACE_Export ACE_TPQ_Entry + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Token Proxy Queue entry. + // Used in the ACE_Token_Proxy_Queue +{ +friend class ACE_Token_Manager; +public: + typedef void (*PTVF) (void *); + + ACE_TPQ_Entry (void); + // Null constructor. + + ACE_TPQ_Entry (const ACE_Token_Proxy *proxy, + const char *client_id); + // Construction. + + ACE_TPQ_Entry (const ACE_TPQ_Entry &rhs); + // Copy constructor. + + ~ACE_TPQ_Entry (void); + // Death. + + void operator= (const ACE_TPQ_Entry &rhs); + // Copy operator use by the queue. + + // = Set/get top of the queue. + ACE_Token_Proxy *proxy (void) const; + void proxy (ACE_Token_Proxy *); + + // = Delta/get nesting level of the entry. + int nesting_level (void) const; + void nesting_level (int delta); + + // = Set/get client_id of the entry. + const char *client_id (void) const; + void client_id (const char *); + + int equal_client_id (const char *id); + // Returns 1 if <id> == client id. Does not check for <id> == 0. + + void set (void (*sleep_hook)(void *)); + // One method for arg and sleep_hook. + + // = Set/get sleep hook of the entry. + void sleep_hook (void (*sh)(void *)); + PTVF sleep_hook (void) const; + + void call_sleep_hook (void); + // Call the sleep hook function or method passing arg. + + ACE_TPQ_Entry *next_; + // Pointer to next in list. + + void dump (void) const; + // Dump the state of the class. + + // = Used to block the thread if an acquire fails with EWOULDBLOCK. + ACE_TOKEN_CONST::MUTEX lock_; + ACE_TOKEN_CONST::COND_VAR cond_var_; + + // = Get/set whether this client is blocked waiting for a token. + int waiting (void) const; + void waiting (int w); + +private: + + int waiting_; + // This client is waiting for a token. + + ACE_Token_Proxy *proxy_; + // Proxy. + + int nesting_level_; + // Nesting level. + + void *arg_; + // Arg. + + char client_id_[ACE_MAXCLIENTIDLEN]; + // Client id. + + void (*sleep_hook_)(void *); + // Sleep hook. +}; + +// ************************************************************ + +// b.. +#if defined (ACE_NO_TSS_TOKENS) +typedef ACE_TPQ_Entry ACE_TPQ_ENTRY; +#else +typedef ACE_TSS<ACE_TPQ_Entry> ACE_TPQ_ENTRY; +#endif /* ACE_NO_TSS_TOKENS */ + +class ACE_Export ACE_TSS_TPQ_Entry : public ACE_TPQ_ENTRY + // = TITLE + // Not a public interface. + // = DESCRIPTION + // ACE_TSS_TPQ_Entry +{ +public: + ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy, + const char *client_id); + // These are passed to the constructor of ACE_TPQ_Entry in + // make_TSS_TYPE + + virtual ACE_TPQ_Entry *make_TSS_TYPE (void) const; + // Allows us to pass args to the construction of the TSS object. + + operator ACE_TPQ_Entry *(void); + // Operator overloading and inheritence don't mix. + + void dump (void) const; + // Dump the state of the class. + +#if defined (ACE_NO_TSS_TOKENS) + ACE_TSS_TPQ_Entry *operator-> (void) + { + return this; + } +#endif + +private: + // = These are passed to the constructor of ACE_TPQ_Entry in + // make_TSS_TYPE + const ACE_Token_Proxy *proxy_; + // Proxy. + const char *client_id_; + // Client_id. +}; + +// ************************************************************ + +class ACE_Token_Proxy_Queue; + +// c.. +class ACE_Export ACE_TPQ_Iterator + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Iterates through ACE_Token_Proxy_Queues. +{ +public: + ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q); + // Construction. + + int next (ACE_TPQ_Entry *&next_item); + // Pass back the <next_item>. Returns 0 when all items have been + // seen, else 1. + + void advance (void); + // Move forward by one element in the queue. + + void dump (void) const; + // Dump the state of an object. + +private: + ACE_TPQ_Entry *current_; +}; + +// 4.. +class ACE_Export ACE_Token_Proxy_Queue + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Token waiter list. + // This queue holds all the token proxies waiting for ownership of + // a token. Along with the proxy reference, it also stores the + // nesting level, client id, and a magic cookie from the proxy. + // This queue stores the ACE_TPQ_Entries by pointer values. It + // DOES NOT make copies. Thus, the user is responsible to ensure + // that the TPQ's stick around. This is motivated by the need to + // reduce dynamic memory allocation. +{ + friend class ACE_TPQ_Iterator; +public: + ACE_Token_Proxy_Queue (void); + // Construction. + + void enqueue (ACE_TPQ_Entry* new_entry, + int position); + // Enqueue a proxy, nesting level, client_id, and a magic cookie at + // the given position in the list. If the position is -1, we + // enqueue at the end of the list (I think). + + const ACE_TPQ_Entry* head (void); + // Top of the queue. + +// int member (const char *id); + // Is this id in the waiter list? + + void dequeue (void); + // Remove the top waiter. + + void remove (const ACE_TPQ_Entry *remove_me); + // Remove the waiter whose proxy ref matches remove_me. + + int size (void); + // The number of waiters. + + void dump (void) const; + // Dump the state of the class. + +protected: + ACE_TPQ_Entry *head_; + // Head. + ACE_TPQ_Entry *tail_; + // Tail. + int size_; + // Size. +}; + +// 5.. +class ACE_Export ACE_Tokens + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Abstract representation of ACE tokens. + // Currently, I don't see a reason for providing an abstract + // interface at this level of the library. As of yet, no one uses + // ACE_Tokens derivatives through this abstract interface except + // for Token_Manager. It only uses the statistical methods which + // are shared by all Tokens. For that reason, it still makes + // since to have a common base class. However, acquire, renew, + // and release do not need to have matching interfaces throughout + // all Tokens. + + // = EXTENDING TOKENS + // To add a new type of token (e.g. semaphore), this class must be + // subtyped to define the new semantics. See ACE_Token_Manager + // for details. +{ +public: + + ACE_Tokens (void); + // Null constructor. + + virtual int acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify) = 0; + // No implementation. + + virtual int tryacquire (ACE_TPQ_Entry *caller) = 0; + // No implementation. + + virtual int renew (ACE_TPQ_Entry *caller, + int requeue_position) = 0; + // No implementation. + + virtual int release (ACE_TPQ_Entry *caller) = 0; + // No implementation. + + void make_owner (ACE_TPQ_Entry *caller); + // Move the caller to the front of the waiter list. This is for use + // with remote mutexes and shadow mutexes. + + void remove (ACE_TPQ_Entry *caller); + // Remove the caller from the waiter list. + + // = Accessor methods. + + typedef ACE_Unbounded_Stack<ACE_TPQ_Entry *> + OWNER_STACK; + // Stack of owners. + + virtual int owners (OWNER_STACK &o, const char *id) = 0; + // Returns a stack of the current owners. Returns -1 on error, 0 on + // success. If <id> is non-zero, returns 1 if id is an owner. + + virtual int is_waiting_for (const char *id) = 0; + // Returns 1 if <id> is waiting for this token. 0 otherwise. + + virtual int is_owner (const char *id) = 0; + // Returns 1 if <id> is an owner of this token. 0 otherwise. + + virtual ACE_Token_Proxy_Queue *waiters (void); + // Return the queue of waiters. + + virtual int no_of_waiters (void); + // Return the number of proxies that are currently waiting to get + // the token. + + const char *owner_id (void); + // The current owner. + + const char* name (void); + // Token name. + + // = Reference counting. These are only called by the + // Token_Manager. + void inc_reference (void); + int dec_reference (void); + + void dump (void) const; + // Dump the state of the class. + + enum TOKEN_TYPES { MUTEX, RWLOCK }; + // These are the Token types supported by the library at ship time. + // There is no restriction on the number of Token types added by + // "3rd parties." These are only necessary for the Token Server. + + virtual int type (void) const = 0; + // Provides a manual RTTI mechanism. This method is used only by + // ACE_Token_Request so that the type of a token can be sent to a + // remote Token Server. + + // = The following methods allow the deadlock detection algorithm to + // check if this token has been visited. + + void visit (int v); + // Mark or unmark the token as visited. + + int visited (void); + // Check if the token has been visited. + + ACE_TPQ_Entry *owner (void); + // All the data of the current owner. + +protected: + + int visited_; + // For the deadlock detection algorithm. + + int reference_count_; + // Reference count. + + ACE_Token_Proxy_Queue waiters_; + // List of client's owning and waiting the token. + + char token_name_[ACE_MAXTOKENNAMELEN]; + // Name of token. +}; + +class ACE_Local_Mutex; + +// 6.. +class ACE_Export ACE_Mutex_Token : public ACE_Tokens + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Class that acquires, renews, and releases a process-local + // synchronization token. + // This class is a more general-purpose synchronization mechanism + // than SunOS 5.x mutexes. For example, it implements "recursive + // mutex" semantics, where a thread that owns the token can + // reacquire it without deadlocking. In addition, threads that are + // blocked awaiting the token are serviced in strict FIFO order as + // other threads release the token (SunOS 5.x mutexes don't strictly + // enforce an acquisition order). +{ +public: + ACE_Mutex_Token (const char* name); + // life + + ~ACE_Mutex_Token (void); + // death + + // = Synchronization operations. + // With acquire, renew, and release, the caller must be specified so + // that multiple proxies (e.g. ACE_Local_Mutex) can use the same + // token. + + virtual int acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify); + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. If ignore_deadlock is passed as 1 and errnum == + // EDEADLK, then deadlock was detected via ace_token_manager. + + virtual int tryacquire (ACE_TPQ_Entry *caller); + // same as acquire, but fails if would block + + virtual int renew (ACE_TPQ_Entry *caller, + int requeue_position); + // An optimized method that efficiently reacquires the token if no + // other threads are waiting. This is useful for situations where + // you don't want to degrade the quality of service if there are + // other threads waiting to get the token. If <requeue_position> == + // -1 and there are other threads waiting to obtain the token we are + // queued at the end of the list of waiters. If <requeue_position> + // > -1 then it indicates how many entries to skip over before + // inserting our thread into the list of waiters (e.g., + // <requeue_position> == 0 means "insert at front of the queue"). + // Renew has the rather odd semantics such that if there are other + // waiting threads it will give up the token even if the + // nesting_level_ > 1. I'm not sure if this is really the right + // thing to do (since it makes it possible for shared data to be + // changed unexpectedly) so use with caution... + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. + + virtual int release (ACE_TPQ_Entry *caller); + // Relinquish the token. If there are any waiters then the next one + // in line gets it. If the caller is not the owner, caller is + // removed from the waiter list. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_Tokens::MUTEX. + + virtual int owners (OWNER_STACK &o, const char *id); + // Returns a stack of the current owners. Returns -1 on error, 0 on + // success. If <id> is non-zero, returns 1 if id is an owner. + + virtual int is_waiting_for (const char *id); + // Returns 1 if <id> is waiting for this token. 0 otherwise. + + virtual int is_owner (const char *id); + // Returns 1 if <id> is an owner of this token. 0 otherwise. + +private: + ACE_TOKEN_CONST::MUTEX lock_; + // ACE_Mutex_Token used to lock internal data structures. +}; + +// 12.. +class ACE_Export ACE_RW_Token : public ACE_Tokens + // = TITLE + // Not a public interface. + // + // = DESCRIPTION + // Class that acquires, renews, and releases a process-local + // synchronization token. + // This class is a more general-purpose synchronization mechanism + // than SunOS 5.x mutexes. For example, it implements "recursive + // mutex" semantics, where a thread that owns the token can + // reacquire it without deadlocking. In addition, threads that are + // blocked awaiting the token are serviced in strict FIFO order as + // other threads release the token (SunOS 5.x mutexes don't strictly + // enforce an acquisition order). +{ +public: + ACE_RW_Token (const char* name); + // Life. + + ~ACE_RW_Token (void); + // Death. + + // = Synchronization operations. + // With acquire, renew, and release, the caller must be specified so + // that multiple proxies (e.g. ACE_Local_Mutex) can use the same + // token. + + virtual int acquire (ACE_TPQ_Entry *caller, + int ignore_deadlock, + int notify); + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. If ignore_deadlock is passed as 1 and errnum == + // EDEADLK, then deadlock was detected via ace_token_manager. + + virtual int tryacquire (ACE_TPQ_Entry *caller); + // same as acquire except fails on would block + + virtual int renew (ACE_TPQ_Entry *caller, + int requeue_position); + // An optimized method that efficiently reacquires the token if no + // other threads are waiting. This is useful for situations where + // you don't want to degrade the quality of service if there are + // other threads waiting to get the token. If <requeue_position> == + // -1 and there are other threads waiting to obtain the token we are + // queued at the end of the list of waiters. If <requeue_position> + // > -1 then it indicates how many entries to skip over before + // inserting our thread into the list of waiters (e.g., + // <requeue_position> == 0 means "insert at front of the queue"). + // Renew has the rather odd semantics such that if there are other + // waiting threads it will give up the token even if the + // nesting_level_ > 1. I'm not sure if this is really the right + // thing to do (since it makes it possible for shared data to be + // changed unexpectedly) so use with caution... + // Returns 0 on success, -1 on failure with ACE_LOG_MSG->errnum() as + // the reason. If errnum == EWOULDBLOCK, and notify == 1, + // ACE_Token_Proxy::sleep_hook() has been called on the current owner + // of the token. + + virtual int release (ACE_TPQ_Entry *caller); + // Relinquish the token. If there are any waiters then the next one + // in line gets it. If the caller is not the owner, caller is + // removed from the waiter list. + + void dump (void) const; + // Dump the state of the class. + + enum PROXY_TYPE { READER, WRITER }; + // These are the types that proxies can be. + + virtual int type (void) const; + // Returns READER or WRITER. + + virtual int owners (OWNER_STACK &o, const char *id); + // Returns a stack of the current owners. Returns -1 on error, 0 on + // success. If <id> is non-zero, returns 1 if id is an owner. + + virtual int is_waiting_for (const char *id); + // Returns 1 if <id> is waiting for this token. 0 otherwise. + + virtual int is_owner (const char *id); + // Returns 1 if <id> is an owner of this token. 0 otherwise. + +protected: + int num_writers_; + // the number of waiting writers. + + ACE_TOKEN_CONST::MUTEX lock_; + // ACE_Mutex_Token used to lock internal data structures. + + void notify_new_owner (ACE_TPQ_Entry *caller); + // Sets the new owner. +}; + +// a.. +class ACE_Token_Name + // = TITLE + // Allows Token_Manger to identify tokens. + // + // = DESCRIPTION + // For now, this is just a string. We need a string class anyway + // to use in ACE_Map_Manager. Having this class (instead of + // SString) allows us to easily change if needed. For instance, + // we may choose to identify tokens by name and *type* in the + // future. +{ +public: + ACE_Token_Name (const char *token_name = 0); + // Construction. + + ACE_Token_Name (const ACE_Token_Name &rhs); + // Copy construction. + + ~ACE_Token_Name (void); + // Death. + + void operator= (const ACE_Token_Name &rhs); + // Copy. + + int operator== (const ACE_Token_Name &rhs) const; + // Comparison. + + const char *name (void) const; + // Token name. + + void name (const char *new_name); + // Token name. + + void dump (void) const; + // Dump the state of the class. + +private: + char token_name_[ACE_MAXTOKENNAMELEN]; + // Name of the token. +}; + + +// 7.. +class ACE_Export ACE_Token_Proxy + // = TITLE + // Abstract representation of ACE tokens. + // + // = DESCRIPTION + // Interface for all Tokens in ACE. This class implements the + // synchronization needed for tokens (condition variables etc.) + // The algorithms for the operations (acquire, release, etc.) + // operate on the generic ACE_Tokens interface. Thus, the _type_ + // of token (mutex, rwlock) can be set at construction of + // ACE_Token_Proxy. You can use all Tokens in ACE through the + // ACE_Token_Proxy by passing the proper values at construction. + // Alternatively, there are class definitions which "know" how to + // do this (ACE_Local_Mutex, ACE_Local_RLock, ACE_Local_WLock). + + // = EXTENDING TOKENS + // To add a new type of token (e.g. semaphore), this class is not + // changed. See ACE_Token_Manager for details. + + // = RESTRICTIONS + // Tokens (e.g. ACE_Mutex_Token) assume that it can always call + // ACE_Token_Proxy::token_acquired () on a new token owner. This + // is not a problem for synchronous use of token proxies (that is, + // when acquires block until successful.) However, for + // implementations of the Token Server, which may use asynch + // operations, the proxy can not go away after an acquire until + // the token is acquired. This is not really a problem, but + // should be understood. +{ +friend class ACE_Token_Manager; +friend class ACE_Token_Invariant_Manager; // For testing. +public: + + // Initialization and termination methods. + ACE_Token_Proxy (void); + // Construction. + + ~ACE_Token_Proxy (void); + // Death. + + virtual int open (const char *name, + int ignore_deadlock = 0, + int debug = 0); + // <name> is the string uniquely identifying the token. + // <ignore_deadlock> can be 1 to disable deadlock notifications. + // <debug> prints debug messages. + + // = The following methods have implementations which are + // independent of the token semantics (mutex, rwlock, etc.) They + // forward operations to the underlying token and perform the + // necessary blocking semantics for operations (condition variables + // etc.) This allows reuse of the blocking code as well as having + // multiple proxies to the same token. + + virtual int acquire (int notify = 0, + void (*sleep_hook)(void *) = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls acquire on the token. Blocks the calling thread if would + // block. + + virtual int renew (int requeue_position = -1, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls renew on the token. Blocks the calling thread if would + // block. + + virtual int tryacquire (void (*sleep_hook)(void *) = 0); + // Calls renew on the token. + + virtual int release (ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls release on the token. + + virtual int remove (ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Calls remove on the token. + + // = Utility methods. + + virtual const char *client_id (void) const; + // Get the client id of the proxy. This is implemented as + // thread-specific data. + + virtual void client_id (const char *client_id); + // Set the client_id for the calling thread. I strongly recommend + // that this not be used unless you really know what you're doing. + // I use this in the Token Server, and it caused many headaches. + + virtual const char *name (void) const; + // Return the name of the token. This is important for use within + // the token servers (local and remote) as well as with token + // collections. So, all derivations of ACE_Token_Proxy must be able to + // stringify some name. The name must uniquely identify a token. + // So, for instance, the token within the reactor should probably be + // called "Reactor Token." + + virtual void sleep_hook (void); + // This should really be called someone_waiting (). + // This is called by ACE_Token_xx's when another proxy enters the + // waiting list and requests that the current token holder be notified. + + virtual void token_acquired (ACE_TPQ_Entry *); + // This is called when a queued (waiting) proxy is removed from the + // waiters list and given the token. + + virtual const char *owner_id (void); + // the client id of the current token holder + + virtual ACE_Token_Proxy *clone (void) const = 0; + // Return a dynamically allocated clone of the derived class. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // This method can be used be Tokens (e.g. Readers/Writer Tokens) to + // distinguish between Proxy types. For instance a Reader proxy + // should return a different type value than a Writer proxy. The + // default implementation returns 0. + +protected: + ACE_Token_Proxy (const ACE_Token_Proxy &); + // Duplication. + + int ignore_deadlock_; + // If this is set, we ignore deadlock. + + int debug_; + // Print a bunch of debug messages. + + ACE_Tokens *token_; + // Reference to the actual logical token. Many ACE_Local_Mutex + // proxies can reference the same ACE_Mutex_Token. + + int handle_options (ACE_Synch_Options &options, + ACE_TOKEN_CONST::COND_VAR &cv); + // Handles cond_var waits. + + ACE_TSS_TPQ_Entry waiter_; + // Waiter info used for asynchronous transactions. + + virtual ACE_Tokens *create_token (const char *name) = 0; + // Make the correct type of ACE_Tokens. This is called by the Token + // Manager. +}; + +// 8.. +class ACE_Export ACE_Null_Token : public ACE_Token_Proxy + // = TITLE + // No op class for nonthreaded platform protocols. +{ +public: + ACE_Null_Token (void) {}; + // Construction. + + virtual int acquire (int /* notify */ = 0, + void (* /* sleep_hook */ )(void *) = 0, + ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Acquire. + + virtual int renew (int /* requeue_position */ = -1, + ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Renew. + + virtual int tryacquire (void (* /* sleep_hook */)(void *) = 0) { return 0; } + // Try acquire. + + virtual int release (ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Release. + + virtual int remove (ACE_Synch_Options & /* options */ = + ACE_Synch_Options::defaults) { return 0; } + // Remove. + + virtual ACE_Token_Proxy *clone (void) const { return new ACE_Null_Token; } + // Return a dynamically allocated clone of the derived class. + + void dump (void) const; + // Dump the state of the class. + + virtual ACE_Tokens *create_token (const char *) { return 0; } + // Do not allow the Token Manager to create us. +}; + +// 9.. +class ACE_Export ACE_Local_Mutex : public ACE_Token_Proxy + // = TITLE + // Class that acquires, renews, and releases a synchronization + // token local to the process. + // + // = DESCRIPTION + // This class is a more general-purpose synchronization mechanism + // than SunOS 5.x mutexes. For example, it implements "recursive + // mutex" semantics, where a thread that owns the token can + // reacquire it without deadlocking. In addition, threads that + // are blocked awaiting the token are serviced in strict FIFO + // order as other threads release the token (SunOS 5.x mutexes + // don't strictly enforce an acquisition order). Lastly, + // ACE_Local_Mutex performs deadlock detection on acquire calls. + // + // = Synchronization operations. + // The interfaces for acquire, tryacquire, renew, release, + // etc. are defined in ACE_Token_Proxy. The semantics for + // ACE_Local_Mutex are that of a mutex. +{ +public: + ACE_Local_Mutex (const char *token_name = 0, + int ignore_deadlock = 0, + int debug = 0); + // <token_name> uniquely id's the token. + // <ignore_deadlock> will allow deadlock to occur (useful for + // testing). <debug> prints a bunch of messages. + + void dump (void) const; + // Dump the state of the class. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Return a new ACE_Local_Mutex. +}; + +// *. +class ACE_Export ACE_Local_RLock : public ACE_Token_Proxy +// = TITLE +// Class that acquires, renews, and releases a readers lock that +// is local to the process. +// +// = DESCRIPTION +// This class implements the reader interface to canonical +// readers/writer locks. Multiple readers can hold the lock +// simultaneously when no writers have the lock. Alternatively, +// when a writer holds the lock, no other participants (readers or +// writers) may hold the lock. This class is a more +// general-purpose synchronization mechanism than SunOS 5.x RLocks. +// For example, it implements "recursive RLock" semantics, where a +// thread that owns the token can reacquire it without deadlocking. +// In addition, threads that are blocked awaiting the token are +// serviced in strict FIFO order as other threads release the token +// (SunOS 5.x RLockes don't strictly enforce an acquisition +// order). +// +// = Synchronization operations. +// The interfaces for acquire, tryacquire, renew, release, etc. are +// defined in ACE_Token_Proxy. The semantics for ACE_Local_RLock +// are that of a readers/writers lock. Acquire for this class +// implies a reader acquisition. That is, multiple clients may +// acquire a lock for read only. +{ +public: + // = Initialization and termination. + + ACE_Local_RLock (const char *token_name = 0, + int ignore_deadlock = 0, + int debug = 0); + // <token_name> uniquely id's the token. + // <ignore_deadlock> will allow deadlock to occur (useful for + // testing). <debug> prints a bunch of messages. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_RW_Token::RLOCK. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Return a new ACE_Local_Mutex. +}; + +// *. +class ACE_Export ACE_Local_WLock : public ACE_Token_Proxy +// = TITLE +// Class that acquires, renews, and releases a writer lock that +// is local to the process. +// +// = DESCRIPTION +// This class implements the writer interface to canonical +// readers/writer locks. Multiple readers can hold the lock +// simultaneously when no writers have the lock. Alternatively, +// when a writer holds the lock, no other participants (readers or +// writers) may hold the lock. This class is a more +// general-purpose synchronization mechanism than SunOS 5.x WLock. +// For example, it implements "recursive WLock" semantics, where a +// thread that owns the token can reacquire it without deadlocking. +// In addition, threads that are blocked awaiting the token are +// serviced in strict FIFO order as other threads release the token +// (SunOS 5.x WLocks don't strictly enforce an acquisition order). +// +// = Synchronization operations. +// The interfaces for acquire, tryacquire, renew, release, +// etc. are defined in ACE_Token_Proxy. The semantics for +// ACE_Local_WLock are that of a readers/writers lock. Acquire +// for this class implies a writer acquisition. That is, only one +// client may hold the lock for writing. +{ +public: + // = Initialization and termination. + + ACE_Local_WLock (const char *token_name = 0, + int ignore_deadlock = 0, + int debug = 0); + // <token_name> uniquely id's the token. + // <ignore_deadlock> will allow deadlock to occur (useful for + // testing). <debug> prints a bunch of messages. + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_RW_Token::WLOCK. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + ACE_Tokens *create_token (const char *name); + // Return a new ACE_Local_Mutex. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Local_Tokens.i" +#endif /* __ACE_INLINE__ */ +#endif /* ACE_LOCAL_MUTEX_H */ diff --git a/ace/Local_Tokens.i b/ace/Local_Tokens.i new file mode 100644 index 00000000000..430c542bd85 --- /dev/null +++ b/ace/Local_Tokens.i @@ -0,0 +1,363 @@ +/* -*- C++ -*- */ +// $Id$ + +// Local_Tokens.i + +ACE_INLINE int +ACE_Token_Proxy::type (void) const +{ + ACE_TRACE ("ACE_Token_Proxy::type"); + return 0; +} + +ACE_INLINE int +ACE_Token_Proxy_Queue::size (void) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::size"); + return this->size_; +} + +// ************************************************************ + +ACE_INLINE int +ACE_TPQ_Entry::waiting (void) const +{ + ACE_TRACE ("ACE_TPQ_Entry::waiting"); + return waiting_; +} + +ACE_INLINE void +ACE_TPQ_Entry::waiting (int v) +{ + ACE_TRACE ("ACE_TPQ_Entry::waiting"); + waiting_ = v; +} + +ACE_INLINE const char * +ACE_TPQ_Entry::client_id (void) const +{ + ACE_TRACE ("ACE_TPQ_Entry::client_id"); + return this->client_id_; +} + +ACE_INLINE ACE_Token_Proxy * +ACE_TPQ_Entry::proxy (void) const +{ + ACE_TRACE ("ACE_TPQ_Entry::proxy"); + return this->proxy_; +} + +ACE_INLINE void +ACE_TPQ_Entry::proxy (ACE_Token_Proxy *proxy) +{ + ACE_TRACE ("ACE_TPQ_Entry::proxy"); + this->proxy_ = proxy; +} + +ACE_INLINE void +ACE_Tokens::remove (ACE_TPQ_Entry *caller) +{ + this->waiters_.remove (caller); +} + +ACE_INLINE int +ACE_Tokens::dec_reference (void) +{ + ACE_TRACE ("ACE_Tokens::dec_reference"); + if (this->reference_count_ == 0) + { + ACE_DEBUG ((LM_DEBUG, "dec_reference already zero")); + return 0; + } + + return --this->reference_count_; +} + +ACE_INLINE void +ACE_Tokens::inc_reference (void) +{ + ACE_TRACE ("ACE_Tokens::inc_reference"); + ++this->reference_count_; +} + +ACE_INLINE ACE_Token_Proxy_Queue * +ACE_Tokens::waiters () +{ + ACE_TRACE ("ACE_Tokens::waiters"); + return &this->waiters_; +} + +ACE_INLINE int +ACE_Tokens::no_of_waiters () +{ + ACE_TRACE ("ACE_Tokens::no_of_waiters"); + return this->waiters_.size (); +} + +ACE_INLINE const ACE_TPQ_Entry * +ACE_Token_Proxy_Queue::head (void) +{ + ACE_TRACE ("ACE_Token_Proxy_Queue::head"); + if (this->head_ == 0) + return 0; + else + return this->head_; +} + +// ************************************************** +// ************************************************** +// ************************************************** + +ACE_INLINE void +ACE_Tokens::visit (int v) +{ + ACE_TRACE ("ACE_Tokens::visit"); + visited_ = v; +} + +ACE_INLINE int +ACE_Tokens::visited (void) +{ + ACE_TRACE ("ACE_Tokens::visited"); + return visited_; +} + +ACE_INLINE ACE_TPQ_Entry * +ACE_Tokens::owner (void) +{ + ACE_TRACE ("ACE_Tokens::owner"); + return (ACE_TPQ_Entry *) this->waiters_.head (); +} + +ACE_INLINE const char* +ACE_Tokens::owner_id () +{ + ACE_TRACE ("ACE_Tokens::owner_id"); + if (this->owner () == 0) + return "no owner"; + else + return this->owner ()->client_id (); +} + +ACE_INLINE const char* +ACE_Tokens::name (void) +{ + ACE_TRACE ("ACE_Tokens::name"); + return this->token_name_; +} + +#if 0 +ACE_INLINE ACE_Token_Proxy * +ACE_Tokens::current_owner (void) +{ + ACE_TRACE ("ACE_Tokens::current_owner"); + // ACE_GUARD_RETURN ??? + + if (this->owner () == 0) + return 0; + else + return this->owner ()->proxy (); +} +#endif /* 0 */ + +// ************************************************************ + +ACE_INLINE int +ACE_Mutex_Token::type (void) const +{ + ACE_TRACE ("ACE_Mutex_Token::type"); + return (int) ACE_Tokens::MUTEX; +} + +// ************************************************************ + +ACE_INLINE int +ACE_RW_Token::type (void) const +{ + ACE_TRACE ("ACE_RW_Token::type"); + return (int) ACE_Tokens::RWLOCK; +} + +// ************************************************************ + +ACE_INLINE int +ACE_TPQ_Entry::nesting_level (void) const +{ + ACE_TRACE ("ACE_TPQ_Entry::nesting_level"); + return this->nesting_level_; +} + +ACE_INLINE void +ACE_TPQ_Entry::nesting_level (int delta) +{ + ACE_TRACE ("ACE_TPQ_Entry::nesting_level"); + this->nesting_level_ += delta; +} + +ACE_INLINE ACE_TPQ_Entry::PTVF +ACE_TPQ_Entry::sleep_hook (void) const +{ + ACE_TRACE ("ACE_TPQ_Entry::sleep_hook"); + return this->sleep_hook_; +} + +ACE_INLINE void +ACE_TPQ_Entry::sleep_hook (void (*sh)(void *)) +{ + ACE_TRACE ("ACE_TPQ_Entry::sleep_hook"); + this->sleep_hook_ = sh; +} + +ACE_INLINE void +ACE_TPQ_Entry::call_sleep_hook (void) +{ + ACE_TRACE ("ACE_TPQ_Entry::call_sleep_hook"); + + // if a function has been registered, call it. + if (this->sleep_hook () != 0) + this->sleep_hook () ((void *) this->proxy ()); + else + // otherwise, call back the sleep_hook method + this->proxy ()->sleep_hook (); +} + +ACE_INLINE int +ACE_TPQ_Entry::equal_client_id (const char *id) +{ + ACE_TRACE ("ACE_TPQ_Entry::equal_client_id"); + return (ACE_OS::strcmp (this->client_id (), id) == 0); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +ACE_INLINE +ACE_Local_Mutex::ACE_Local_Mutex (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Local_Mutex::ACE_Local_Mutex"); + this->open (token_name, ignore_deadlock, debug); +} + +ACE_INLINE void +ACE_Token_Name::name (const char *new_name) +{ + ACE_TRACE ("ACE_Token_Name::name"); + + if (new_name == 0) + new_name = "no name"; + + int n = ACE_OS::strlen (new_name) + 1; + + if (n >= ACE_MAXTOKENNAMELEN) + n = ACE_MAXTOKENNAMELEN - 1; + + ACE_OS::strncpy (this->token_name_, (char *) new_name, n); +} + +ACE_INLINE const char* +ACE_Token_Name::name (void) const +{ + ACE_TRACE ("ACE_Token_Name::name"); + return this->token_name_; +} + +ACE_INLINE ACE_Token_Proxy * +ACE_Local_Mutex::clone (void) const +{ + return new ACE_Local_Mutex (token_->name (), + ignore_deadlock_, + debug_); +} + +ACE_INLINE ACE_Tokens * +ACE_Local_Mutex::create_token (const char *name) +{ + return new ACE_Mutex_Token (name); +} + +// ************************************************************ + +ACE_INLINE +ACE_Local_RLock::ACE_Local_RLock (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Local_RLock::ACE_Local_RLock"); + this->open (token_name, ignore_deadlock, debug); +} + +ACE_INLINE ACE_Tokens * +ACE_Local_RLock::create_token (const char *name) +{ + return new ACE_RW_Token (name); +} + +ACE_INLINE int +ACE_Local_RLock::type (void) const +{ + return ACE_RW_Token::READER; +} + +ACE_INLINE ACE_Token_Proxy * +ACE_Local_RLock::clone (void) const +{ + return new ACE_Local_RLock (token_->name (), + ignore_deadlock_, + debug_); +} + +// ************************************************************ + +ACE_INLINE +ACE_Local_WLock::ACE_Local_WLock (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Local_WLock::ACE_Local_WLock"); + this->open (token_name, ignore_deadlock, debug); +} + +ACE_INLINE ACE_Tokens * +ACE_Local_WLock::create_token (const char *name) +{ + return new ACE_RW_Token (name); +} + +ACE_INLINE int +ACE_Local_WLock::type (void) const +{ + return ACE_RW_Token::WRITER; +} + +ACE_INLINE ACE_Token_Proxy * +ACE_Local_WLock::clone (void) const +{ + return new ACE_Local_WLock (token_->name (), + ignore_deadlock_, + debug_); +} + +// ************************************************************ + + +ACE_INLINE void +ACE_Token_Name::operator= (const ACE_Token_Name &rhs) +{ + ACE_TRACE ("ACE_Token_Name::operator="); + if (&rhs == this) + return; + else + this->name (rhs.name ()); +} + +ACE_INLINE int +ACE_Token_Name::operator== (const ACE_Token_Name &rhs) const +{ + ACE_TRACE ("ACE_Token_Name::operator=="); + + // the name and type must be the same + return (ACE_OS::strcmp (this->token_name_, rhs.name ()) == 0); +} diff --git a/ace/Local_Tokens_T.cpp b/ace/Local_Tokens_T.cpp new file mode 100644 index 00000000000..da978100488 --- /dev/null +++ b/ace/Local_Tokens_T.cpp @@ -0,0 +1,56 @@ +// Local_Tokens_T.cpp +// $Id$ + +#if !defined (ACE_LOCAL_TOKENS_T_C) +#define ACE_LOCAL_TOKENS_T_C + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Local_Tokens_T.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Local_Tokens_T.i" +#endif /* __ACE_INLINE__ */ + +template <class TYPE> +ACE_Token_Name<TYPE>::ACE_Token_Name (void) +{ + ACE_TRACE ("ACE_Token_Name::ACE_Token_Name"); +} + +template <class TYPE> +ACE_Token_Name<TYPE>::ACE_Token_Name (const char *token_name, + TYPE type) +{ + ACE_TRACE ("ACE_Token_Name::ACE_Token_Name"); + this->type (type); + this->name (token_name); +} + +template <class TYPE> +ACE_Token_Name<TYPE>::ACE_Token_Name (const ACE_Token_Name<TYPE> &rhs) +{ + ACE_TRACE ("ACE_Token_Name::ACE_Token_Name"); + this->type (rhs.type ()); + this->name (rhs.name ()); +} + +template <class TYPE> +ACE_Token_Name<TYPE>::~ACE_Token_Name () +{ + ACE_TRACE ("ACE_Token_Name::~ACE_Token_Name"); +} + +template <class TYPE> void +ACE_Token_Name<TYPE>::dump (void) const +{ + ACE_TRACE ("ACE_Token_Name::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Name::dump:\n" + " token_name_ = %s\n" + " type_ = %d\n", + token_name_, (int) type_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#endif /* ACE_LOCAL_TOKENS_T_C */ diff --git a/ace/Local_Tokens_T.h b/ace/Local_Tokens_T.h new file mode 100644 index 00000000000..c8a5f21db2a --- /dev/null +++ b/ace/Local_Tokens_T.h @@ -0,0 +1,95 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Local_Tokens_T +// +// = AUTHOR +// Tim Harrison (harrison@cs.wustl.edu) +// +// = DESCRIPTION +// This file contains definitions for the following classes: +// +// public: +// ACE_Token_Name +// +// ============================================================================ + +#if !defined (ACE_LOCAL_TOKENS_T_H) +#define ACE_LOCAL_TOKENS_T_H + +#include "ace/ACE.h" + +template <class TYPE> +class ACE_Token_Name + // = TITLE + // Allows Token_Manger to identify tokens. + // + // = DESCRIPTION + // A 2-tuple of token name and token type. For now, we're going + // to use int's instead of ACE_Token_Manager::TOKEN_TYPE. This is + // because of the different ways the compilers are instantiating + // the templates in the token manager. +{ +public: + ACE_Token_Name (void); + // for map manager + + ACE_Token_Name (const char *token_name, + TYPE type); + // construction + + ACE_Token_Name (const ACE_Token_Name<TYPE> &rhs); + // copy construction + + ~ACE_Token_Name (void); + // death + + void operator= (const ACE_Token_Name<TYPE> &rhs); + // copy + + int operator== (const ACE_Token_Name<TYPE> &rhs) const; + // comparison + + const char *name (void) const; + // token name + + void name (const char *new_name); + // token name + + TYPE type (void) const; + // token type + + void type (TYPE type); + // token type + + void dump (void) const; + // Dump the state of the class. + +private: + char token_name_[ACE_MAXTOKENNAMELEN]; + // Name of the token. + + TYPE type_; + // Type of the token. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Local_Tokens_T.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Local_Tokens_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Local_Tokens_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_LOCAL_TOKENS_T_H */ diff --git a/ace/Local_Tokens_T.i b/ace/Local_Tokens_T.i new file mode 100644 index 00000000000..1eb8881a464 --- /dev/null +++ b/ace/Local_Tokens_T.i @@ -0,0 +1,65 @@ +/* -*- C++ -*- */ +// $Id$ + +// Local_Tokens_T.i + +template <class TYPE> ACE_INLINE void +ACE_Token_Name<TYPE>::operator= (const ACE_Token_Name<TYPE> &rhs) +{ + ACE_TRACE ("ACE_Token_Name<TYPE>::operator="); + if (&rhs == this) + return; + else + { + this->type (rhs.type ()); + this->name (rhs.name ()); + } +} + +template <class TYPE> ACE_INLINE int +ACE_Token_Name<TYPE>::operator== (const ACE_Token_Name<TYPE> &rhs) const +{ + ACE_TRACE ("ACE_Token_Name<TYPE>::operator=="); + + // the name and type must be the same + return (ACE_OS::strcmp (this->token_name_, rhs.name ()) == 0 + && rhs.type () == type_); +} + +template <class TYPE> ACE_INLINE const char* +ACE_Token_Name<TYPE>::name (void) const +{ + ACE_TRACE ("ACE_Token_Name<TYPE>::name"); + return this->token_name_; +} + +template <class TYPE> ACE_INLINE void +ACE_Token_Name<TYPE>::name (const char *new_name) +{ + ACE_TRACE ("ACE_Token_Name<TYPE>::name"); + + if (new_name == 0) + return; + + int n = ACE_OS::strlen (new_name) + 1; + + if (n > ACE_MAXTOKENNAMELEN) + n = ACE_MAXTOKENNAMELEN; + + ACE_OS::strncpy (this->token_name_, (char *) new_name, n); +} + +template <class TYPE> ACE_INLINE TYPE +ACE_Token_Name<TYPE>::type (void) const +{ + ACE_TRACE ("ACE_Token_Name<TYPE>::type"); + return this->type_; +} + +template <class TYPE> ACE_INLINE void +ACE_Token_Name<TYPE>::type (TYPE type) +{ + ACE_TRACE ("ACE_Token_Name<TYPE>::type"); + this->type_ = type; +} + diff --git a/ace/Log_Msg.cpp b/ace/Log_Msg.cpp new file mode 100644 index 00000000000..31015bddf5b --- /dev/null +++ b/ace/Log_Msg.cpp @@ -0,0 +1,895 @@ +// Log_Msg.cpp +// $Id$ + +#define ACE_BUILD_DLL +// We need this to get the status of ACE_NTRACE... +#include "ace/config.h" + +// Turn off tracing for the duration of this file. +#if defined (ACE_NTRACE) +#undef ACE_NTRACE +#endif /* ACE_NTRACE */ +#define ACE_NTRACE 1 + +// This must come first to avoid "order of include" problems... + +#if !defined (ACE_HAS_INLINED_OSCALLS) && !defined (ACE_WIN32) +#define ACE_HAS_INLINED_OSCALLS +#include "ace/ACE.h" +#undef ACE_HAS_INLINED_OSCALLS +#else +#include "ace/ACE.h" +#endif /* !ACE_HAS_INLINED_OSCALLS */ + +#include "ace/Thread.h" +#include "ace/Synch.h" + +#include "ace/Log_Msg.h" + +// 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... +#if defined (ACE_WIN32) +#include "ace/SPIPE_Connector.h" +static ACE_SPIPE_Stream message_queue_; +#else +#include "ace/FIFO_Send_Msg.h" +static ACE_FIFO_Send_Msg message_queue_; +#endif /* ACE_WIN32 */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Log_Msg) + +#if defined (ACE_MT_SAFE) +// Synchronize output operations. +static ACE_Recursive_Thread_Mutex *lock_ = 0; + +static ACE_thread_key_t key_; + +/* static */ +void +ACE_TSS_cleanup (void *ptr) +{ + delete ptr; +} +#endif /* ACE_MT_SAFE */ + +ACE_Log_Msg * +ACE_Log_Msg::instance (void) +{ +#if defined (ACE_MT_SAFE) +#if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +#error "Platform must support thread-specific storage if threads are used..." +#else + // TSS Singleton implementation. + + static int once_ = 0; + static int count_ = 0; + + if (once_ == 0) + { + // Synchronize Singleton creation (note that this may lose big + // if the compiler doesn't perform thread-safe initialization of + // local statics...). + static ACE_Thread_Mutex keylock_; + ACE_thread_mutex_t &lock = (ACE_thread_mutex_t &) keylock_.lock (); + + ACE_OS::thread_mutex_lock (&lock); + if (once_ == 0) + { + // Initialize the static recursive lock here. Note that we + // can't rely on the constructor being called at this point. + ACE_NEW_RETURN (lock_, ACE_Recursive_Thread_Mutex, 0); + + if (ACE_OS::thr_keycreate (&key_, + &ACE_TSS_cleanup) != 0) + { + ACE_OS::thread_mutex_unlock (&lock); + return 0; // Major problems, this should *never* happen! + } + once_ = 1; + } + ACE_OS::thread_mutex_unlock (&lock); + } + + ACE_Log_Msg *tss_log_msg = 0; + + // Get the tss_log_msg from thread-specific storage. Note that no locks + // are required here... + if (ACE_OS::thr_getspecific (key_, + (void **) &tss_log_msg) == -1) + return 0; // This should not happen! + + // Check to see if this is the first time in for this thread. + if (tss_log_msg == 0) + { + // Allocate memory off the heap and store it in a pointer in + // thread-specific storage (on the stack...). + + ACE_NEW_RETURN (tss_log_msg, ACE_Log_Msg, 0); + + // Store the dynamically allocated pointer in thread-specific + // storage. + if (ACE_OS::thr_setspecific (key_, + (void *) tss_log_msg) != 0) + return 0; // Major problems, this should *never* happen! + } + + return tss_log_msg; +#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +#else + // Singleton implementation. + static ACE_Log_Msg log_msg; + + return &log_msg; +#endif /* defined (ACE_MT_SAFE) */ +} + +// Name of the local host. +const char *ACE_Log_Msg::local_host_ = 0; + +// Records the program name. +const char *ACE_Log_Msg::program_name_ = 0; + +// Default is to use stderr. +u_long ACE_Log_Msg::flags_ = ACE_Log_Msg::STDERR; + +// Process id of the current process. +pid_t ACE_Log_Msg::pid_ = -1; + +// Current offset of msg_[]. +int ACE_Log_Msg::msg_off_ = 0; + +// Call after a fork to resynchronize the PID and PROGRAM_NAME +// variables. + +void +ACE_Log_Msg::sync (const char *prog_name) +{ + ACE_TRACE ("ACE_Log_Msg::sync"); + if (prog_name) + { + ACE_OS::free ((void *) ACE_Log_Msg::program_name_); + ACE_Log_Msg::program_name_ = ACE_OS::strdup (prog_name); + } + ACE_Log_Msg::msg_off_ = 0; +} + +u_long +ACE_Log_Msg::flags (void) +{ + ACE_TRACE ("ACE_Log_Msg::flags"); + u_long result; + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, *lock_, 0)); + + result = ACE_Log_Msg::flags_; + return result; +} + +void +ACE_Log_Msg::set_flags (u_long flgs) +{ + ACE_TRACE ("ACE_Log_Msg::set_flags"); + ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, *lock_)); + + ACE_SET_BITS (ACE_Log_Msg::flags_, flgs); +} + +void +ACE_Log_Msg::clr_flags (u_long flgs) +{ + ACE_TRACE ("ACE_Log_Msg::clr_flags"); + ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, *lock_)); + + ACE_CLR_BITS (ACE_Log_Msg::flags_, flgs); +} + +int +ACE_Log_Msg::acquire (void) +{ + ACE_TRACE ("ACE_Log_Msg::acquire"); +#if defined (ACE_MT_SAFE) + return lock_->acquire (); +#else + return 0; +#endif /* ACE_MT_SAFE */ +} + +u_long +ACE_Log_Msg::priority_mask (u_long n_mask) +{ + u_long o_mask = this->priority_mask_; + this->priority_mask_ = n_mask; + return o_mask; +} + +u_long +ACE_Log_Msg::priority_mask (void) +{ + return this->priority_mask_; +} + +int +ACE_Log_Msg::release (void) +{ + ACE_TRACE ("ACE_Log_Msg::release"); + +#if defined (ACE_MT_SAFE) + return lock_->release (); +#else + return 0; +#endif /* ACE_MT_SAFE */ +} + +ACE_Log_Msg::ACE_Log_Msg (void) + : status_ (0), + errnum_ (0), + linenum_ (0), + ostream_ (0), + restart_ (1), // Restart by default... + thr_state_ (0), + trace_depth_ (0), + thr_handle_ (0), + trace_active_ (0), + tracing_enabled_ (0), // Off by default? + priority_mask_ (LM_SHUTDOWN // By default, all priorities are enabled. + | LM_TRACE + | LM_DEBUG + | LM_INFO + | LM_NOTICE + | LM_WARNING + | LM_STARTUP + | LM_ERROR + | LM_CRITICAL + | LM_ALERT + | LM_EMERGENCY) +{ + ACE_TRACE ("ACE_Log_Msg::ACE_Log_Msg"); +} + +// Open the sender-side of the Message ACE_Queue. + +int +ACE_Log_Msg::open (const char *prog_name, + u_long flags, + const char *logger_key) +{ + ACE_TRACE ("ACE_Log_Msg::open"); + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, *lock_, -1)); + + if (prog_name) + ACE_Log_Msg::program_name_ = ACE_OS::strdup (prog_name); + + int status = 0; + + // Note that if we fail to open the message queue the default action + // is to use stderr (set via static initialization in the + // ACE_Log_Msg.C file). + + if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER)) + { + if (logger_key == 0) + status = -1; + else +#if defined (ACE_WIN32) + { + ACE_SPIPE_Connector con; + status = con.connect (message_queue_, ACE_SPIPE_Addr (logger_key)); + } +#else + status = message_queue_.open (logger_key); +#endif /* ACE_WIN32 */ + + if (status == -1) + ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR); + else + ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER); + } + + // Remember, ACE_Log_Msg::STDERR bit is on by default... + if (status != -1 + && ACE_BIT_ENABLED (flags, ACE_Log_Msg::STDERR) == 0) + ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR); + + if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::VERBOSE)) + ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE); + + if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::OSTREAM)) + { + ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::OSTREAM); + ACE_LOG_MSG->msg_ostream (&cerr); + } + if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::SILENT)) + ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SILENT); + + return status; +} + +// Valid Options (prefixed by '%', as in printf format strings) include: +// 'a': exit the program at this point (var-argument is the exit status!) +// 'c': print a character +// 'i', 'd': print a decimal number +// 'e', 'E', 'f', 'F', 'g', 'G': print a double +// 'l', print line number where an error occurred. +// 'N': print file name where the error occurred. +// 'n': print the name of the program (or "<unknown>" if not set) +// 'o': print as an octal number +// 'P': format the current process id +// 'p': format the appropriate errno value from sys_errlist +// 'r': call the function pointed to by the corresponding argument +// 'R': print return status +// 'S': format the appropriate _sys_siglist entry corresponding to var-argument. +// 's': format a character string +// 'T': print timestamp in hour:minute:sec:usec format. +// 't': print thread id (1 if single-threaded) +// 'u': print as unsigned int +// 'X', 'x': print as a hex number +// '%': format a single percent sign, '%' + +ssize_t +ACE_Log_Msg::log (ACE_Log_Priority log_priority, + const char *format_str, ...) +{ + ACE_TRACE ("ACE_Log_Msg::log"); + + // Start of variable args section. + va_list argp; + + va_start (argp, format_str); + + int result = this->log (format_str, log_priority, argp); + + va_end (argp); + + return result; +} + +ssize_t +ACE_Log_Msg::log (const char *format_str, + ACE_Log_Priority log_priority, + va_list argp) +{ + ACE_TRACE ("ACE_Log_Msg::log"); + // External decls. + extern int sys_nerr; + typedef void (*PTF)(...); + + ACE_Log_Record log_record (log_priority, + ACE_OS::time ((time_t *) 0), + this->getpid ()); + char *bp = this->msg (); + int abort_prog = 0; + int exit_value = 0; + int result = 0; + char *format = ACE_OS::strdup (format_str); + char *save_p = format; // Remember pointer for ACE_OS::free() + + if (format == 0) + return -1; + + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE)) + { + // Prepend the program name onto this message + + if (ACE_Log_Msg::program_name_ != 0) + { + for (const char *s = ACE_Log_Msg::program_name_; (*bp = *s) != '\0'; s++) + bp++; + + *bp++ = '|'; + } + } + + while (*format != '\0') + { + // Copy input to output until we encounter a %, however a + // % followed by another % is not a format specification. + + if (*format != '%') + *bp++ = *format++; + else if (format[1] == '%') // An "escaped" '%' (just print one '%'). + { + *bp++ = *format++; // Store first % + format++; // but skip second % + } + else + { + char c; // high use character + char *fp; // local format pointer + int wpc; // width/precision cnt + const int CONTINUE = 0; + const int SKIP_SPRINTF = -1; // We must skip the sprintf phase + const int SKIP_NUL_LOCATE = -2; // Skip locating the NUL character + int type = CONTINUE; // conversion type + int w[2]; // width/precision vals + + // % starts a format specification that ends with one of + // "arnPpSsdciouxXfFeEgG". An optional width and/or precision + // (indicated by an "*") may be encountered prior to the + // nend of the specification, each consumes an int arg. + // A call to sprintf() does the actual conversion. + + fp = format++; // Remember beginning of format. + wpc = 0; // Assume no width/precision seen. + + while (type == CONTINUE) + { + switch (*format++) + { + case 'a': // Abort program after handling all of format string. + type = SKIP_SPRINTF; + abort_prog = 1; + exit_value = va_arg (argp, int); + ACE_OS::sprintf (bp, ""); // Make sure to NUL-terminate this... + break; + case 'l': + ACE_OS::sprintf (bp, "%d", this->linenum ()); + type = SKIP_SPRINTF; + break; + case 'N': + { + const char *file = this->file (); + ACE_OS::sprintf (bp, "%s", file ? file : "<unknown file>"); + type = SKIP_SPRINTF; + break; + } + case 'n': // Print the name of the program. + type = SKIP_SPRINTF; + ACE_OS::strcpy (bp, ACE_Log_Msg::program_name_ ? + ACE_Log_Msg::program_name_ : "<unknown>"); + break; + 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. + { + 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)); + else + ACE_OS::sprintf (bp, "%s: <unknown error> = %d", + va_arg (argp, char *), errno); + break; + } + 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; + case 'r': // Run (invoke) this subroutine. + { + int osave = ACE_Log_Msg::msg_off_; + + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SILENT)) + *bp++ = '{'; + ACE_Log_Msg::msg_off_ = bp - this->msg_; + + type = SKIP_SPRINTF; + (*va_arg (argp, PTF))(); + + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SILENT)) + { + bp += ACE_OS::strlen (bp); + *bp++ = '}'; + } + *bp = '\0'; + + ACE_Log_Msg::msg_off_ = osave; + break; + } + case 'S': // format the string associated with this signal number. + { + int sig = va_arg (argp, int); + type = SKIP_SPRINTF; +#if defined (ACE_HAS_SYS_SIGLIST) + if (sig >= 0 && sig < NSIG) + ACE_OS::strcpy (bp, _sys_siglist[sig]); + else + ACE_OS::sprintf (bp, "<unknown signal> %d", sig); +#else + ACE_OS::sprintf (bp, "signal %d", sig); +#endif /* ACE_HAS_SYS_SIGLIST */ + break; + } + case 'T': /* format the timestamp*/ + { + type = SKIP_SPRINTF; + char day_and_time[35]; + ACE_OS::sprintf (bp, "%s", + ACE::timestamp (day_and_time, + sizeof day_and_time)); + break; + } + case 't': // format thread id. + type = SKIP_SPRINTF; +#if defined (ACE_WIN32) + ACE_OS::sprintf (bp, "%u", ACE_Thread::self ()); +#else + ACE_hthread_t t_id; + ACE_Thread::self (t_id); + ACE_OS::sprintf (bp, "%u", t_id); +#endif /* ACE_WIN32 */ + break; + case 's': + type = 1 + wpc; // 1, 2, 3 + break; + case 'd': case 'c': case 'i': case 'o': + case 'u': case 'x': case 'X': + type = 4 + wpc; // 4, 5, 6 + break; + case 'F': case 'f': case 'e': case 'E': + case 'g': case 'G': + type = 7 + wpc; // 7, 8, 9 + break; + case '*': // consume width/precision + w[wpc++] = va_arg (argp, int); + break; + default: + // ? + break; + } + } + + if (type != SKIP_SPRINTF) + { + c = *format; // Remember char before we overwrite. + *format = 0; // Overwrite, terminating format. + + switch (type) + { + case 1: + ACE_OS::sprintf (bp, fp, va_arg (argp, char *)); + break; + case 2: + ACE_OS::sprintf (bp, fp, w[0], va_arg (argp, char *)); + bp += w[0]; + type = SKIP_NUL_LOCATE; + break; + case 3: + ACE_OS::sprintf (bp, fp, w[0], w[1], va_arg (argp, char *)); + bp += w[0]; + type = SKIP_NUL_LOCATE; + break; + case 4: + ACE_OS::sprintf (bp, fp, va_arg (argp, int)); + break; + case 5: + ACE_OS::sprintf (bp, fp, w[0], va_arg (argp, int)); + break; + case 6: + ACE_OS::sprintf (bp, fp, w[0], w[1], va_arg (argp, int)); + break; + case 7: + ACE_OS::sprintf (bp, fp, va_arg (argp, double)); + break; + case 8: + ACE_OS::sprintf (bp, fp, w[0], va_arg (argp, double)); + break; + case 9: + ACE_OS::sprintf (bp, fp, w[0], w[1], va_arg (argp, double)); + break; + } + *format = c; // Restore char we overwrote. + } + + if (type != SKIP_NUL_LOCATE) + while (*bp != '\0') // Locate end of bp. + bp++; + } + } + + *bp = '\0'; // Terminate bp, but don't auto-increment this! + + ACE_OS::free (ACE_MALLOC_T (save_p)); + + // Only print the message if "SILENT" mode is disabled and the + // <priority_mask_> hasn't been reset to exclude this logging + // priority. + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SILENT) == 0 + && ACE_BIT_ENABLED (this->priority_mask_, log_priority)) + { + // Copy the message from thread-specific storage into the + // transfer buffer (this can be optimized away by changing other + // code...). + log_record.msg_data (this->msg ()); + this->stop_tracing (); + + // Make sure that the lock is help during all this. + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, *lock_, -1)); + + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR)) + log_record.print (ACE_Log_Msg::local_host_, + ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE), + stderr, + bp - this->msg ()); + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER)) + { + ACE_Str_Buf log_msg ((void *) &log_record, + int (log_record.length ())); +#if defined (ACE_HAS_STREAM_PIPES) + result = message_queue_.send (int (log_record.type ()), + &log_msg); +#elif !defined (ACE_WIN32) + result = message_queue_.send (log_msg); +#else + result = message_queue_.send ((const ACE_Str_Buf *) &log_msg, + (const ACE_Str_Buf *) 0); +#endif /* ACE_HAS_STREAM_PIPES */ + } + // Format the message and print it to stderr and/or ship it + // off to the log_client daemon, and/or print it to the + // ostream. This must come last, after the other two print + // operations (see the ACE_Log_Record::print method for + // details). + + if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::OSTREAM) + && this->msg_ostream () != 0) + log_record.print (ACE_Log_Msg::local_host_, + ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE), + *this->msg_ostream (), + bp - this->msg ()); + this->start_tracing (); + } + + if (abort_prog) + ACE_OS::exit (exit_value); + + return result; +} + +// Calls log to do the actual print, but formats first. + +int +ACE_Log_Msg::log_hexdump (ACE_Log_Priority log_priority, + char *buffer, + int size) +{ + char buf[ACE_Log_Record::MAXLOGMSGLEN - ACE_Log_Record::VERBOSE_LEN - 58]; + // 58 for the HEXDUMP header; + + char msg_buf[80]; + + buf[0] = 0; // in case size = 0 + + int len = ACE::format_hexdump (buffer, size, buf, sizeof buf); + + int sz = ::sprintf (msg_buf, "HEXDUMP %d bytes", size); + if (len < size) + ::sprintf (msg_buf + sz, " (showing first %d bytes)", len); + + // Now print out the formatted buffer. + this->log (log_priority, "%s\n%s", msg_buf, buf); + return 0; +} + +void +ACE_Log_Msg::set (const char *filename, + int line, + int status, + int err, + int rs, + ostream *os) +{ + ACE_TRACE ("ACE_Log_Msg::set"); + this->file (filename); + this->linenum (line); + this->op_status (status); + this->errnum (err); + this->restart (rs); + this->msg_ostream (os); +} + +void +ACE_Log_Msg::dump (void) const +{ + ACE_TRACE ("ACE_Log_Msg::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "status_ = %d\n", this->status_)); + ACE_DEBUG ((LM_DEBUG, "\nerrnum_ = %d\n", this->errnum_)); + ACE_DEBUG ((LM_DEBUG, "\nlinenum_ = %d\n", this->linenum_)); + ACE_DEBUG ((LM_DEBUG, "\nfile_ = %s\n", this->file_)); + ACE_DEBUG ((LM_DEBUG, "\nmsg_ = %s\n", this->msg_)); + ACE_DEBUG ((LM_DEBUG, "\nrestart_ = %s\n", this->restart_)); + ACE_DEBUG ((LM_DEBUG, "\nostream_ = %x\n", this->ostream_)); + ACE_DEBUG ((LM_DEBUG, "\nprogram_name_ = %s\n", this->program_name_ ? this->program_name_ : "<unknown>")); + ACE_DEBUG ((LM_DEBUG, "\nlocal_host_ = %s\n", this->local_host_ ? this->local_host_ : "<unknown>")); + ACE_DEBUG ((LM_DEBUG, "\npid_ = %d\n", this->getpid ())); + ACE_DEBUG ((LM_DEBUG, "\nflags_ = %d\n", this->flags_)); + ACE_DEBUG ((LM_DEBUG, "\ntrace_depth_ = %d\n", this->trace_depth_)); + ACE_DEBUG ((LM_DEBUG, "\trace_active_ = %d\n", this->trace_active_)); + ACE_DEBUG ((LM_DEBUG, "\tracing_enabled_ = %d\n", this->tracing_enabled_)); + ACE_DEBUG ((LM_DEBUG, "\npriority_mask_ = %s\n", this->priority_mask_)); + if (this->thr_state_ != 0) + ACE_DEBUG ((LM_DEBUG, "\thr_state_ = %d\n", *this->thr_state_)); + ACE_DEBUG ((LM_DEBUG, "\nmsg_off_ = %d\n", this->msg_off_)); + message_queue_.dump (); +#if defined (ACE_MT_SAFE) + lock_->dump (); + // Synchronize output operations. +#endif /* ACE_MT_SAFE */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Log_Msg::op_status (int status) +{ + this->status_ = status; +} + +int +ACE_Log_Msg::op_status (void) +{ + return this->status_; +} + +void +ACE_Log_Msg::restart (int r) +{ + this->restart_ = r; +} + +int +ACE_Log_Msg::restart (void) +{ + return this->restart_; +} + +int +ACE_Log_Msg::errnum (void) +{ + return this->errnum_; +} + +void +ACE_Log_Msg::errnum (int e) +{ + this->errnum_ = e; +} + +int +ACE_Log_Msg::linenum (void) +{ + return this->linenum_; +} + +void +ACE_Log_Msg::linenum (int l) +{ + this->linenum_ = l; +} + +int +ACE_Log_Msg::inc (void) +{ + return this->trace_depth_++; +} + +int +ACE_Log_Msg::dec (void) +{ + return --this->trace_depth_; +} + +int +ACE_Log_Msg::trace_active (void) +{ + return this->trace_active_; +} + +void +ACE_Log_Msg::trace_active (int value) +{ + this->trace_active_ = value; +} + +ACE_Thread_State * +ACE_Log_Msg::thr_state (void) +{ + return this->thr_state_; +} + +void +ACE_Log_Msg::thr_state (ACE_Thread_State *ts) +{ + this->thr_state_ = ts; +} + +ACE_hthread_t * +ACE_Log_Msg::thr_handle (void) +{ + return this->thr_handle_; +} + +void +ACE_Log_Msg::thr_handle (ACE_hthread_t *th) +{ + this->thr_handle_ = th; +} + +// Enable the tracing facility on a per-thread basis. + +void +ACE_Log_Msg::start_tracing (void) +{ + this->tracing_enabled_ = 1; +} + +// Disable the tracing facility on a per-thread basis. + +void +ACE_Log_Msg::stop_tracing (void) +{ + this->tracing_enabled_ = 0; +} + +int +ACE_Log_Msg::tracing_enabled (void) +{ + return this->tracing_enabled_; +} + +const char * +ACE_Log_Msg::file (void) +{ + return this->file_; +} + +void +ACE_Log_Msg::file (const char *s) +{ + ACE_OS::strncpy (this->file_, s, + sizeof this->file_); +} + +char * +ACE_Log_Msg::msg (void) +{ + return this->msg_ + ACE_Log_Msg::msg_off_; +} + +void +ACE_Log_Msg::msg (char *m) +{ + ACE_OS::strncpy (this->msg_, m, + sizeof this->msg_); +} + +ostream * +ACE_Log_Msg::msg_ostream (void) +{ + return this->ostream_; +} + +void +ACE_Log_Msg::msg_ostream (ostream *m) +{ + this->ostream_ = m; +} + +void +ACE_Log_Msg::local_host (const char *s) +{ + if (s) + { + ACE_OS::free ((void *) ACE_Log_Msg::local_host_); + ACE_Log_Msg::local_host_ = ACE_OS::strdup (s); + } +} + +const char * +ACE_Log_Msg::local_host (void) const +{ + return ACE_Log_Msg::local_host_; +} + +pid_t +ACE_Log_Msg::getpid (void) const +{ + if (ACE_Log_Msg::pid_ == -1) + ACE_Log_Msg::pid_ = ACE_OS::getpid (); + + return ACE_Log_Msg::pid_; +} + diff --git a/ace/Log_Msg.h b/ace/Log_Msg.h new file mode 100644 index 00000000000..724fe70dee3 --- /dev/null +++ b/ace/Log_Msg.h @@ -0,0 +1,359 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Log_Msg.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LOG_MSG_H) +#define ACE_LOG_MSG_H + +// This stuff must come first to avoid problems with circular +// headers... + +// The following ASSERT macro is courtesy of Alexandre Karev +// <akg@na47sun05.cern.ch>. +#if defined (ACE_NDEBUG) +#define ACE_ASSERT(x) +#else +#define ACE_ASSERT(X) \ + do { if(!(X)) { int __ace_error = errno; ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \ + ace___->set (__FILE__, __LINE__, -1, __ace_error, ace___->restart (), ace___->msg_ostream ()); \ + ace___->log (LM_ERROR, "ACE_ASSERT: file %N, line %l assertion failed for '%s'.%a\n", #X, -1); \ + } } while (0) +#endif /* ACE_NDEBUG */ + +#if defined (ACE_NLOGGING) +#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(X) +#define ACE_DEBUG(X) +#define ACE_ERROR_INIT(VALUE, FLAGS) +#else +#define ACE_HEX_DUMP(X) \ + do { int __ace_error = errno; \ + ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \ + ace___->set (__FILE__, __LINE__, 0, errno, ace___->restart (), \ + ace___->msg_ostream ()); \ + ace___->log_hexdump X; \ + } while (0) +#define ACE_RETURN(Y) \ + do { int __ace_error = errno; \ + ACE_Log_Msg::instance ()->set (__FILE__, __LINE__, Y, __ace_error); \ + return Y; \ + } while (0) +#define ACE_ERROR_RETURN(X, Y) \ + do { int __ace_error = errno; \ + ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \ + ace___->set (__FILE__, __LINE__, Y, __ace_error, ace___->restart (), ace___->msg_ostream ()); \ + ace___->log X; \ + return Y; \ + } while (0) +#define ACE_ERROR(X) \ + do { int __ace_error = errno; \ + ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \ + ace___->set (__FILE__, __LINE__, -1, __ace_error, ace___->restart (), ace___->msg_ostream ()); \ + ace___->log X; \ + } while (0) +#define ACE_DEBUG(X) \ + do { int __ace_error = errno; \ + ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \ + ace___->set (__FILE__, __LINE__, 0, errno, ace___->restart (), ace___->msg_ostream ()); \ + ace___->log X; \ + } while (0) +#define ACE_ERROR_INIT(VALUE, FLAGS) \ + do { \ + ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \ + ace___->set_flags (FLAGS); ace___->op_status (VALUE); \ + } while (0) +#endif /* ACE_NLOGGING */ + +#include "ace/Log_Record.h" + +#define ACE_LOG_MSG ACE_Log_Msg::instance () + +class ACE_Export ACE_Log_Msg + // = TITLE + // Provides a variable length argument message logging + // abstraction. + // + // = DESCRIPTION + // This class is very flexible since it allows formatted error + // messages to be printed in a thread-safe manner to stderr or a + // distributed logger. Moreover, the message is kept in a + // thread-specific storage location, which can be used to + // communicate errors between framework methods and callers. +{ +public: + enum /* Logger Flags */ + { + STDERR = 01, + // Write messages to stderr. + LOGGER = 02, + // Write messages to the local client logger deamon. + OSTREAM = 04, + // Write messages to the ostream * stored in thread-specific + // storage. + VERBOSE = 010, + // Display messages in a verbose manner + SILENT = 020 + // Do not print messages at all (just leave in thread-specific + // storage for later inspection). + }; + + // = Initialization and termination routines. + + static ACE_Log_Msg *instance (void); + // Returns a pointer to the Singleton. + + ACE_Log_Msg (void); + // Initialize logger. + + int open (const char *prog_name, + u_long options_flags = ACE_Log_Msg::STDERR, + const char *logger_key = 0); + // Initialize the ACE error handling facility. <prog_name> is the + // name of the executable program. <flags> are a bitwise-or of + // options flags passed to the Logger (see the enum above for the valid + // values). If the <LOGGER> bit in <flags> is enabled then + // <logger_key> is the name of ACE_FIFO rendezvous point where the + // local client logger daemon is listening for logging messages. + + // = Set/get the options flags. + + void set_flags (u_long f); + // Enable the bits in the logger's options flags. + void clr_flags (u_long f); + // Disable the bits in the logger's options flags. + u_long flags (void); + // Return the bits in the logger's options flags. + + // = Operations that allow applications to acquire and release the + // synchronization lock used internally by the ACE_Log_Msg + // implementation. This allows applications to hold the lock + // atomically over a number of calls to ACE_Log_Msg. + int acquire (void); + // Acquire the internal lock. + int release (void); + // Release the internal lock. + + void sync (const char *program_name); + // Call after doing a fork() to resynchronize the PID and + // PROGRAM_NAME variables. + + // = Set/get methods. Note that these are non-static and thus will + // be thread-specific. + + void op_status (int status); + // Set the result of the operation status (by convention, -1 means error). + + int op_status (void); + // Get the result of the operation status (by convention, -1 means error). + + void errnum (int); + // Set the value of the errnum (by convention this corresponds to errno). + + int errnum (void); + // Get the value of the errnum (by convention this corresponds to errno). + + void linenum (int); + // Set the line number where an error occurred. + + int linenum (void); + // Get the line number where an error occurred. + + void file (const char *); + // Set the file name where an error occurred. + + const char *file (void); + // Get the file name where an error occurred. + + void msg (char *); + // Set the message that describes what type of error occurred. + + char *msg (void); + // Get the message that describes what type of error occurred. + + void restart (int); + // Set the field that indicates whether interrupted calls should be + // restarted. + + int restart (void); + // Get the field that indicates whether interrupted calls should be + // restarted. + + void msg_ostream (ostream *); + // Set the ostream that is used to print error messages. + + ostream *msg_ostream (void); + // Get the ostream that is used to print error messages. + + // = Nesting depth increment and decrement. + int inc (void); + int dec (void); + + // = Get/set trace active status. + int trace_active (void); + void trace_active (int value); + + // = Get/set the current thread state. + ACE_Thread_State *thr_state (void); + void thr_state (ACE_Thread_State *); + + // = Get/set the current thread ACE_hthread_t. + ACE_hthread_t *thr_handle (void); + void thr_handle (ACE_hthread_t *); + + // = Stop/start/query tracing status on a per-thread basis... + void stop_tracing (void); + void start_tracing (void); + int tracing_enabled (void); + + // = Get/set the priority mask. + u_long priority_mask (void); + // Get the current <ACE_Log_Priority> mask. + u_long priority_mask (u_long); + // Set the <ACE_Log_Priority> mask, returns original mask. + + pid_t getpid (void) const; + // Optimize reading of the pid (avoids a system call if the + // value is cached...). + + // = Set/get the name of the local host. + const char *local_host (void) const; + void local_host (const char *); + + void set (const char *file, + int line, + int op_status = -1, + int errnum = 0, + int restart = 1, + ostream *os = 0); + // Set the line number, file name, operational status, error number, + // restart flag, and ostream. This combines all the other set + // methods into a single method. + + ssize_t log (ACE_Log_Priority priority, const char *format, ...); + // Format a message to the thread-safe ACE logging mechanism. Valid + // options (prefixed by '%', as in printf format strings) include: + // 'a': exit the program at this point (var-argument is the exit status!) + // 'c': print a character + // 'i', 'd': print a decimal number + // 'e', 'E', 'f', 'F', 'g', 'G': print a double + // 'l', print line number where an error occurred. + // 'N': print file name where the error occurred. + // 'n': print the name of the program (or "<unknown>" if not set) + // 'o': print as an octal number + // 'P': print out the current process id + // 'p': print out the appropriate errno value from sys_errlist + // 'r': call the function pointed to by the corresponding argument + // 'R': print return status + // 'S': print out the appropriate _sys_siglist entry corresponding to var-argument. + // 's': print out a character string + // 'T': print timestamp in hour:minute:sec:usec format. + // 't': print thread id (1 if single-threaded) + // 'u': print as unsigned int + // 'X', 'x': print as a hex number + // '%': print out a single percent sign, '%' + + ssize_t log (const char *format, ACE_Log_Priority priority, va_list argp); + // An alternative logging mechanism that makes it possible to + // integrate variable argument lists from other logging mechanisms + // into the ACE mechanism. + + int log_hexdump (ACE_Log_Priority log_priority, + char *buffer, + int size); + // Method to log hex dump. This is useful for debugging. Calls + // <log> to do the actual print, but formats first to make the chars + // printable. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int status_; + // Status of operation (-1 means failure, >= 0 means success). + + int errnum_; + // Type of error that occurred (see <sys/errno.h>). + + int linenum_; + // Line number where the error occurred. + + char file_[MAXNAMELEN]; + // File where the error occurred. + + char msg_[ACE_Log_Record::MAXLOGMSGLEN]; + // The error message. + + int restart_; + // Indicates whether we should restart system calls that are + // interrupted. + + ostream *ostream_; + // The ostream where logging messages can be written. + + int trace_depth_; + // Depth of the nesting for printing traces. + + int trace_active_; + // Are we already within an ACE_Trace constructor call? + + int tracing_enabled_; + // Are we allowing tracing in this thread? + + ACE_Thread_State *thr_state_; + // If we're running in the context of an <ACE_Thread_Manager> this + // will point to the <thr_state_> field in the + // <ACE_Thread_Descriptor>. Threads can use this to rapidly + // determine if they've got a cancellation pending. + + ACE_hthread_t *thr_handle_; + // If we're running in the context of an <ACE_Thread_Manager> this + // will point to the <thr_handle_> field in the + // <ACE_Thread_Descriptor>. Threads can use this to rapidly + // determine their real ACE_hthread_t. + + u_long priority_mask_; + // Keeps track of all the <ACE_Log_Priority> values that are + // currently enabled. Default is for all logging priorities to be + // enabled. + + // = The following fields are *not* kept in thread-specific storage + // since we only want one instance for the entire process! + + static const char *program_name_; + // Records the program name. + + static const char *local_host_; + // Name of the local host (used when printing messages). + + static pid_t pid_; + // Process id of the current process. + + static u_long flags_; + // Options flags. + + static int msg_off_; + // Offset of msg_[]. +}; + +// #if defined (__ACE_INLINE__) +// #include "ace/Log_Msg.i" +// #endif /* __ACE_INLINE__ */ +#endif /* ACE_LOG_MSG_H */ diff --git a/ace/Log_Msg.i b/ace/Log_Msg.i new file mode 100644 index 00000000000..20edd3a6058 --- /dev/null +++ b/ace/Log_Msg.i @@ -0,0 +1,6 @@ +/* -*- C++ -*- */ +// $Id$ + +// Log_Msg.i + + diff --git a/ace/Log_Priority.h b/ace/Log_Priority.h new file mode 100644 index 00000000000..26b2a5f64d6 --- /dev/null +++ b/ace/Log_Priority.h @@ -0,0 +1,73 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Log_Priority.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LM_PRIORITY_H) +#define ACE_LM_PRIORITY_H + +enum ACE_Log_Priority + // = TITLE + // This data type indicates the relative priorities of the + // logging messages, from lowest to highest priority. + // + // = DESCRIPTION + // These values are defined using powers of two so that it's + // possible to form a mask to turn the on or off dynamically. +{ + // = Note, this first argument *must* start at 1! + + LM_SHUTDOWN = 01, + // Shutdown the logger (decimal 1). + + LM_TRACE = 02, + // Messages indicating function-calling sequence (decimal 2). + + LM_DEBUG = 04, + // Messages that contain information normally of use only when + // debugging a program (decimal 4). + + LM_INFO = 010, + // Informational messages (decimal 8). + + LM_NOTICE = 020, + // Conditions that are not error conditions, but that may require + // special handling (decimal 16). + + LM_WARNING = 040, + // Warning messages (decimal 32). + + LM_STARTUP = 0100, + // Initialize the logger (decimal 64). + + LM_ERROR = 0200, + // Error messages (decimal 128). + + LM_CRITICAL = 0400, + // Critical conditions, such as hard device errors (decimal 256). + + LM_ALERT = 01000, + // A condition that should be corrected immediately, such as a + // corrupted system database (decimal 512). + + LM_EMERGENCY = 02000, + // A panic condition. This is normally broadcast to all users + // (decimal 1024). + + LM_MAX = LM_EMERGENCY + // The maximum logging priority. +}; + +#endif /* ACE_LM_PRIORITY_H */ diff --git a/ace/Log_Record.cpp b/ace/Log_Record.cpp new file mode 100644 index 00000000000..cee731cb0da --- /dev/null +++ b/ace/Log_Record.cpp @@ -0,0 +1,136 @@ +// Log_Record.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Log_Record.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_Log_Record) + +void +ACE_Log_Record::dump (void) const +{ + // ACE_TRACE ("ACE_Log_Record::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "type_ = %d\n", this->type_)); + ACE_DEBUG ((LM_DEBUG, "\nlength_ = %d\n", this->length_)); + ACE_DEBUG ((LM_DEBUG, "\nlength_ = %d\n", this->time_stamp_)); + ACE_DEBUG ((LM_DEBUG, "\ntime_stamp_ = %s\n", this->pid_)); + ACE_DEBUG ((LM_DEBUG, "\nmsg_data_ = %s\n", this->msg_data_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Log_Record::msg_data (const char *data) +{ + // ACE_TRACE ("ACE_Log_Record::msg_data"); + ACE_OS::strncpy (this->msg_data_, data, ACE_Log_Record::MAXLOGMSGLEN); + this->round_up (); +} + +ACE_Log_Record::ACE_Log_Record (ACE_Log_Priority lp, + long ts, + long p) + : type_ (long (lp)), + length_ (0), + time_stamp_ (ts), + pid_ (p) +{ + // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record"); +} + +void +ACE_Log_Record::round_up (void) +{ + // ACE_TRACE ("ACE_Log_Record::round_up"); + // Determine the length of the payload. + int len = (sizeof *this - MAXLOGMSGLEN) + + (ACE_OS::strlen (this->msg_data_) + 1); + + // Round up to the alignment. + this->length_ = 1 + ((len + ACE_Log_Record::ALIGN_WORDB - 1) + & ~(ACE_Log_Record::ALIGN_WORDB - 1)); +} + +ACE_Log_Record::ACE_Log_Record (void) + : type_ (0), + length_ (0), + time_stamp_ (0), + pid_ (0) +{ + // ACE_TRACE ("ACE_Log_Record::ACE_Log_Record"); +} + +// Print out the record on the stderr stream with the appropriate +// format. + +int +ACE_Log_Record::print (const char host_name[], + int verbose, + FILE *fp, + size_t len) +{ + // ACE_TRACE ("ACE_Log_Record::print"); + + if (verbose) + { + time_t now = this->time_stamp_; + char ctp[26]; // 26 is a magic number... + + if (ACE_OS::ctime_r (&now, ctp, sizeof ctp) == 0) + return -1; + + /* 01234567890123456789012345 */ + /* Wed Oct 18 14:25:36 1989n0 */ + + ctp[24] = '\0'; + + if (host_name == 0) + host_name = "<local_host>"; + + return ACE_OS::fprintf (fp, "%s@%s@%d@%d@%s", + ctp + 4, host_name, this->pid_, + this->type_, this->msg_data_); + } + else + return ACE_OS::fprintf (fp, "%s", this->msg_data_); +} + +int +ACE_Log_Record::print (const char host_name[], + int verbose, + ostream &s, + size_t len) +{ + // ACE_TRACE ("ACE_Log_Record::print"); + + if (verbose) + { + time_t now = this->time_stamp_; + char ctp[26]; // 26 is a magic number... + if (ACE_OS::ctime_r (&now, ctp, sizeof ctp) == 0) + return -1; + + /* 01234567890123456789012345 */ + /* Wed Oct 18 14:25:36 1989n0 */ + + ctp[24] = '\0'; + + if (host_name == 0) + host_name = "<local_host>"; + + s << (ctp + 4) + << '@' + << host_name + << '@' + << this->pid_ + << '@' + << this->type_ + << '@'; + } + + s << this->msg_data_; + s.flush (); + return 0; +} diff --git a/ace/Log_Record.h b/ace/Log_Record.h new file mode 100644 index 00000000000..273e185c3c6 --- /dev/null +++ b/ace/Log_Record.h @@ -0,0 +1,135 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Log_Record.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_LM_RECORD_H) +#define ACE_LM_RECORD_H + +#include "ace/ACE.h" +#include "ace/Log_Priority.h" + +class ACE_Export ACE_Log_Record +{ + // = TITLE + // Defines the structure of an ACE logging record. +public: +friend ostream &operator << (ostream &, ACE_Log_Record &); + enum + { + MAXLOGMSGLEN = BUFSIZ * 4, + // Maximum size of a logging message. + + ALIGN_WORDB = 8, + // Most restrictive alignment. + + VERBOSE_LEN = 128 + // Size used by verbose mode. + // 20 (date) + 15 (host_name) + 10 (pid) + 10 (type) + 4 (@) ... + + // ? (progname) + }; + + // = Initialization + ACE_Log_Record (void); + ACE_Log_Record (ACE_Log_Priority lp, + long time_stamp, + long pid); + // Create a <Log_Record> and set its priority, time stamp, and + // process id. + + int print (const char host_name[], + int verbose = 1, + FILE *fp = stderr, + size_t msg_data_len = 0); + // Write the contents of the logging record to the appropriate + // <FILE>. + + int print (const char host_name[], + int verbose, + ostream &stream, + size_t msg_data_len = 0); + // Write the contents of the logging record to the appropriate + // <ostream>. + + // = Marshall/demarshall + void encode (void); + // Encode the <Log_Record> for transmission on the network. + + void decode (void); + // Decode the <Log_Record> received from the network. + + // = Set/get methods + + long type (void) const; + // Get the type of the <Log_Record>. + + void type (long); + // Set the type of the <Log_Record>. + + long length (void) const; + // Get the length of the <Log_Record>. + + void length (long); + // Set the length of the <Log_Record>. + + long time_stamp (void) const; + // Get the time stamp of the <Log_Record>. + + void time_stamp (long); + // Set the time stamp of the <Log_Record>. + + long pid (void) const; + // Get the process id of the <Log_Record>. + + void pid (long); + // Set the process id of the <Log_Record>. + + char *msg_data (void); + // Get the message data of the <Log_Record>. + + void msg_data (const char *data); + // Set the message data of the <Log_Record>. + + void msg_data_len (size_t len); + // Set the size of the message data of the <Log_Record>. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + void round_up (void); + // Round up to the alignment restrictions. + + long type_; + // Type of logging record + + long length_; + // length of the logging record + + long time_stamp_; + // Time logging record generated + + long pid_; + // Id of process that generated the record + + char msg_data_[MAXLOGMSGLEN]; + // Logging record data +}; + +#include "ace/Log_Record.i" +#endif /* ACE_LM_Record_H */ diff --git a/ace/Log_Record.i b/ace/Log_Record.i new file mode 100644 index 00000000000..8ddba60122d --- /dev/null +++ b/ace/Log_Record.i @@ -0,0 +1,88 @@ +/* -*- C++ -*- */ +// $Id$ + +// Log_Record.i + +inline void +ACE_Log_Record::encode (void) +{ + ACE_TRACE ("ACE_Log_Record::encode"); + this->type_ = htonl (this->type_); + this->length_ = htonl (this->length_); + this->time_stamp_ = htonl (this->time_stamp_); + this->pid_ = htonl (this->pid_); +} + +inline void +ACE_Log_Record::decode (void) +{ + ACE_TRACE ("ACE_Log_Record::decode"); + this->type_ = ntohl (this->type_); + this->time_stamp_ = ntohl (this->time_stamp_); + this->pid_ = ntohl (this->pid_); + this->length_ = ntohl (this->length_); +} + +inline long +ACE_Log_Record::type (void) const +{ + ACE_TRACE ("ACE_Log_Record::type"); + return this->type_; +} + +inline void +ACE_Log_Record::type (long t) +{ + ACE_TRACE ("ACE_Log_Record::type"); + this->type_ = t; +} + +inline long +ACE_Log_Record::length (void) const +{ + ACE_TRACE ("ACE_Log_Record::length"); + return this->length_; +} + +inline void +ACE_Log_Record::length (long l) +{ + ACE_TRACE ("ACE_Log_Record::length"); + this->length_ = l; +} + +inline long +ACE_Log_Record::time_stamp (void) const +{ + ACE_TRACE ("ACE_Log_Record::time_stamp"); + return this->time_stamp_; +} + +inline void +ACE_Log_Record::time_stamp (long ts) +{ + ACE_TRACE ("ACE_Log_Record::time_stamp"); + this->time_stamp_ = ts; +} + +inline long +ACE_Log_Record::pid (void) const +{ + ACE_TRACE ("ACE_Log_Record::pid"); + return this->pid_; +} + +inline void +ACE_Log_Record::pid (long p) +{ + ACE_TRACE ("ACE_Log_Record::pid"); + this->pid_ = p; +} + +inline char * +ACE_Log_Record::msg_data (void) +{ + ACE_TRACE ("ACE_Log_Record::msg_data"); + return this->msg_data_; +} + diff --git a/ace/Makefile b/ace/Makefile new file mode 100644 index 00000000000..36abc2e2f0e --- /dev/null +++ b/ace/Makefile @@ -0,0 +1,2107 @@ +#---------------------------------------------------------------------------- +# @(#)Makefile 1.1 10/18/96 +# +# Makefile for the entire ACE release +#---------------------------------------------------------------------------- + +MAKEFILE = Makefile +LIB = libACE.a +SHLIB = libACE.so + +FILES = ACE \ + Activation_Queue \ + Addr \ + ARGV \ + CORBA_Handler \ + CORBA_Ref \ + DEV \ + DEV_Addr \ + DEV_Connector \ + DEV_IO \ + Dump \ + Dynamic \ + Event_Handler \ + FIFO \ + FIFO_Recv \ + FIFO_Recv_Msg \ + FIFO_Send \ + FIFO_Send_Msg \ + FILE \ + FILE_Addr \ + FILE_Connector \ + FILE_IO \ + Get_Opt \ + Handle_Set \ + High_Res_Timer \ + INET_Addr \ + IO_Cntl_Msg \ + IO_SAP \ + IPC_SAP \ + Local_Name_Space \ + Local_Tokens \ + LSOCK \ + LSOCK_Acceptor \ + LSOCK_CODgram \ + LSOCK_Connector \ + LSOCK_Dgram \ + LSOCK_Stream \ + Log_Msg \ + Log_Record \ + Malloc \ + Mem_Map \ + Memory_Pool \ + Message_Block \ + Method_Object \ + Name_Proxy \ + Name_Request_Reply \ + Name_Space \ + Naming_Context \ + Obstack \ + OS \ + Parse_Node \ + Pipe \ + Proactor \ + Process \ + Process_Manager \ + Profile_Timer \ + Reactor \ + ReactorEx \ + Read_Buffer \ + Remote_Name_Space \ + Remote_Tokens \ + SOCK \ + SOCK_Acceptor \ + SOCK_CODgram \ + SOCK_Connector \ + SOCK_Dgram \ + SOCK_Dgram_Bcast \ + SOCK_IO \ + SOCK_Dgram_Mcast \ + SOCK_Stream \ + SPIPE \ + SPIPE_Acceptor \ + SPIPE_Addr \ + SPIPE_Connector \ + SPIPE_Stream \ + SString \ + Service_Config \ + Service_Manager \ + Service_Object \ + Service_Record \ + Service_Repository \ + Shared_Memory_MM \ + Shared_Memory_SV \ + Shared_Object \ + Signal \ + SV_Message \ + SV_Message_Queue \ + SV_Semaphore_Complex \ + SV_Semaphore_Simple \ + SV_Shared_Memory \ + Synch \ + Synch_Options \ + System_Time \ + TLI \ + TLI_Acceptor \ + TLI_Connector \ + TLI_Stream \ + Thread \ + Thread_Manager \ + Time_Request_Reply \ + Time_Value \ + Timer_Queue \ + Token \ + Token_Collection \ + Token_Invariants \ + Token_Manager \ + Token_Request_Reply \ + Trace \ + TTY_IO \ + UNIX_Addr \ + UPIPE_Acceptor \ + UPIPE_Connector \ + UPIPE_Stream \ + XtReactor + +TEMPLATE_FILES = \ + Acceptor \ + Auto_Ptr \ + Connector \ + Dump_T \ + Dynamic_Service \ + Event_Handler_T \ + Future \ + Local_Name_Space_T \ + Local_Tokens_T \ + Malloc_T \ + Map_Manager \ + Message_Queue \ + Module \ + Set \ + Singleton \ + Stack \ + Strategies \ + Stream \ + Stream_Modules \ + Svc_Handler \ + Synch_T \ + Task \ + Typed_SV_Message \ + Typed_SV_Message_Queue + +DEFS = $(addsuffix .h,$(FILES)) Svc_Conf_Tokens.h +DEFS += $(addsuffix .i,$(FILES)) +LSRC = $(addsuffix .cpp,$(FILES)) \ + Svc_Conf_l.cpp Svc_Conf_y.cpp +LSRC2 = $(addsuffix .cpp,$(TEMPLATE_FILES)) + +BUILD = $(VLIB) $(VSHLIB) $(SHLIBA) + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU +include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU +include $(WRAPPER_ROOT)/include/makeinclude/rules.nonested.GNU +include $(WRAPPER_ROOT)/include/makeinclude/rules.lib.GNU +include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +Svc_Conf_y.cpp: Svc_Conf.y + $(YACC) -d Svc_Conf.y + sed -e "s/char *getenv/char *ace_foo/g" -e "s/= getenv/= ACE_OS::getenv/g" -e "s/yyerrlab://g" -e "s/yynewerror://g" -e "s/yy/ace_yy/g" < y.tab.c > /tmp/$@ + cp /tmp/$@ $@ + $(RM) -f /tmp/$@ + sed -e "s/yy/ace_yy/g" < y.tab.h >> /tmp/$@ + cp /tmp/$@ Svc_Conf_Tokens.h + $(RM) -f /tmp/$@ + +Svc_Conf_l.cpp: Svc_Conf.l + $(LEX) -t -I Svc_Conf.l > $@ + sed -e "s/unistd/stdio/g" -e "s/yy/ace_yy/g" -e "s/free( ptr );/free( ACE_MALLOC_T (ptr) );/g" -e "s/realloc( ptr, size );/realloc( ACE_MALLOC_T (ptr), size );/g" < $@ > /tmp/$@ + cp /tmp/$@ $@ + $(RM) -f /tmp/$@ + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +.obj/ACE.o .shobj/ACE.so: ACE.cpp \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i +.obj/Activation_Queue.o .shobj/Activation_Queue.so: Activation_Queue.cpp \ + $(WRAPPER_ROOT)/ace/Activation_Queue.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Message_Queue.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \ + $(WRAPPER_ROOT)/ace/Message_Queue.cpp \ + $(WRAPPER_ROOT)/ace/Message_Queue.i \ + $(WRAPPER_ROOT)/ace/Method_Object.h +.obj/Addr.o .shobj/Addr.so: Addr.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.i +.obj/ARGV.o .shobj/ARGV.so: ARGV.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/ARGV.h \ + $(WRAPPER_ROOT)/ace/ARGV.i +.obj/CORBA_Handler.o .shobj/CORBA_Handler.so: CORBA_Handler.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/CORBA_Handler.h \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/CORBA_Handler.i +.obj/CORBA_Ref.o .shobj/CORBA_Ref.so: CORBA_Ref.cpp \ + $(WRAPPER_ROOT)/ace/CORBA_Ref.h \ + $(WRAPPER_ROOT)/ace/CORBA_Ref.i +.obj/DEV.o .shobj/DEV.so: DEV.cpp \ + $(WRAPPER_ROOT)/ace/DEV.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.i \ + $(WRAPPER_ROOT)/ace/DEV_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/DEV.i +.obj/DEV_Addr.o .shobj/DEV_Addr.so: DEV_Addr.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/DEV_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/DEV_Addr.i +.obj/DEV_Connector.o .shobj/DEV_Connector.so: DEV_Connector.cpp \ + $(WRAPPER_ROOT)/ace/DEV_Connector.h \ + $(WRAPPER_ROOT)/ace/DEV_IO.h \ + $(WRAPPER_ROOT)/ace/DEV.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.i \ + $(WRAPPER_ROOT)/ace/DEV_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/DEV.i \ + $(WRAPPER_ROOT)/ace/DEV_IO.i \ + $(WRAPPER_ROOT)/ace/DEV_Connector.i +.obj/DEV_IO.o .shobj/DEV_IO.so: DEV_IO.cpp \ + $(WRAPPER_ROOT)/ace/DEV_IO.h \ + $(WRAPPER_ROOT)/ace/DEV.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.i \ + $(WRAPPER_ROOT)/ace/DEV_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/DEV.i \ + $(WRAPPER_ROOT)/ace/DEV_IO.i +.obj/Dump.o .shobj/Dump.so: Dump.cpp \ + $(WRAPPER_ROOT)/ace/Dump.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Dump_T.h \ + $(WRAPPER_ROOT)/ace/Dump_T.cpp +.obj/Dynamic.o .shobj/Dynamic.so: Dynamic.cpp \ + $(WRAPPER_ROOT)/ace/Dynamic.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Dynamic.i +.obj/Event_Handler.o .shobj/Event_Handler.so: Event_Handler.cpp \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.i +.obj/FIFO.o .shobj/FIFO.so: FIFO.cpp \ + $(WRAPPER_ROOT)/ace/FIFO.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/FIFO.i +.obj/FIFO_Recv.o .shobj/FIFO_Recv.so: FIFO_Recv.cpp \ + $(WRAPPER_ROOT)/ace/FIFO_Recv.h \ + $(WRAPPER_ROOT)/ace/FIFO.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/FIFO_Recv.i +.obj/FIFO_Recv_Msg.o .shobj/FIFO_Recv_Msg.so: FIFO_Recv_Msg.cpp \ + $(WRAPPER_ROOT)/ace/FIFO_Recv_Msg.h \ + $(WRAPPER_ROOT)/ace/FIFO_Recv.h \ + $(WRAPPER_ROOT)/ace/FIFO.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/FIFO_Recv.i \ + $(WRAPPER_ROOT)/ace/FIFO_Recv_Msg.i +.obj/FIFO_Send.o .shobj/FIFO_Send.so: FIFO_Send.cpp \ + $(WRAPPER_ROOT)/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/ace/FIFO.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/FIFO_Send.i +.obj/FIFO_Send_Msg.o .shobj/FIFO_Send_Msg.so: FIFO_Send_Msg.cpp \ + $(WRAPPER_ROOT)/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/ace/FIFO.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/ace/FIFO_Send_Msg.i +.obj/FILE.o .shobj/FILE.so: FILE.cpp \ + $(WRAPPER_ROOT)/ace/FILE.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.i \ + $(WRAPPER_ROOT)/ace/FILE_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/FILE.i +.obj/FILE_Addr.o .shobj/FILE_Addr.so: FILE_Addr.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/FILE_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/FILE_Addr.i +.obj/FILE_Connector.o .shobj/FILE_Connector.so: FILE_Connector.cpp \ + $(WRAPPER_ROOT)/ace/FILE_Connector.h \ + $(WRAPPER_ROOT)/ace/FILE_IO.h \ + $(WRAPPER_ROOT)/ace/FILE.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.i \ + $(WRAPPER_ROOT)/ace/FILE_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/FILE.i \ + $(WRAPPER_ROOT)/ace/FILE_IO.i \ + $(WRAPPER_ROOT)/ace/FILE_Connector.i +.obj/FILE_IO.o .shobj/FILE_IO.so: FILE_IO.cpp \ + $(WRAPPER_ROOT)/ace/FILE_IO.h \ + $(WRAPPER_ROOT)/ace/FILE.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.i \ + $(WRAPPER_ROOT)/ace/FILE_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/FILE.i \ + $(WRAPPER_ROOT)/ace/FILE_IO.i +.obj/Get_Opt.o .shobj/Get_Opt.so: Get_Opt.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Get_Opt.h \ + $(WRAPPER_ROOT)/ace/Get_Opt.i +.obj/Handle_Set.o .shobj/Handle_Set.so: Handle_Set.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.i +.obj/High_Res_Timer.o .shobj/High_Res_Timer.so: High_Res_Timer.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/High_Res_Timer.h \ + $(WRAPPER_ROOT)/ace/High_Res_Timer.i +.obj/INET_Addr.o .shobj/INET_Addr.so: INET_Addr.cpp \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.i +.obj/IO_Cntl_Msg.o .shobj/IO_Cntl_Msg.so: IO_Cntl_Msg.cpp +.obj/IO_SAP.o .shobj/IO_SAP.so: IO_SAP.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IO_SAP.h \ + $(WRAPPER_ROOT)/ace/IO_SAP.i +.obj/IPC_SAP.o .shobj/IPC_SAP.so: IPC_SAP.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i +.obj/Local_Name_Space.o .shobj/Local_Name_Space.so: Local_Name_Space.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Local_Name_Space.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.cpp \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.i \ + $(WRAPPER_ROOT)/ace/SString.h \ + $(WRAPPER_ROOT)/ace/Local_Name_Space_T.h \ + $(WRAPPER_ROOT)/ace/Name_Space.h \ + $(WRAPPER_ROOT)/ace/Name_Proxy.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Name_Request_Reply.h \ + $(WRAPPER_ROOT)/ace/Naming_Context.h \ + $(WRAPPER_ROOT)/ace/Local_Name_Space_T.cpp +.obj/Local_Tokens.o .shobj/Local_Tokens.so: Local_Tokens.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Local_Tokens.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Stack.h \ + $(WRAPPER_ROOT)/ace/Stack.cpp \ + $(WRAPPER_ROOT)/ace/Stack.i \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.cpp \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.i \ + $(WRAPPER_ROOT)/ace/Token_Manager.h \ + $(WRAPPER_ROOT)/ace/Local_Tokens.i +.obj/LSOCK.o .shobj/LSOCK.so: LSOCK.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/LSOCK.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/LSOCK.i +.obj/LSOCK_Acceptor.o .shobj/LSOCK_Acceptor.so: LSOCK_Acceptor.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Acceptor.h \ + $(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/UNIX_Addr.h \ + $(WRAPPER_ROOT)/ace/LSOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/LSOCK.h \ + $(WRAPPER_ROOT)/ace/LSOCK.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Acceptor.i +.obj/LSOCK_CODgram.o .shobj/LSOCK_CODgram.so: LSOCK_CODgram.cpp \ + $(WRAPPER_ROOT)/ace/LSOCK_CODgram.h \ + $(WRAPPER_ROOT)/ace/LSOCK.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/LSOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_CODgram.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_CODgram.i \ + $(WRAPPER_ROOT)/ace/LSOCK_CODgram.i +.obj/LSOCK_Connector.o .shobj/LSOCK_Connector.so: LSOCK_Connector.cpp \ + $(WRAPPER_ROOT)/ace/LSOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/LSOCK.h \ + $(WRAPPER_ROOT)/ace/LSOCK.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/UNIX_Addr.h \ + $(WRAPPER_ROOT)/ace/LSOCK_Connector.i +.obj/LSOCK_Dgram.o .shobj/LSOCK_Dgram.so: LSOCK_Dgram.cpp \ + $(WRAPPER_ROOT)/ace/LSOCK_Dgram.h \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/ace/LSOCK.h \ + $(WRAPPER_ROOT)/ace/LSOCK.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Dgram.i +.obj/LSOCK_Stream.o .shobj/LSOCK_Stream.so: LSOCK_Stream.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/LSOCK.h \ + $(WRAPPER_ROOT)/ace/LSOCK.i \ + $(WRAPPER_ROOT)/ace/LSOCK_Stream.i +.obj/Log_Msg.o .shobj/Log_Msg.so: Log_Msg.cpp \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/OS.i \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/ace/FIFO.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/ace/FIFO_Send_Msg.i +.obj/Log_Record.o .shobj/Log_Record.so: Log_Record.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i +.obj/Malloc.o .shobj/Malloc.so: Malloc.cpp \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Malloc.i +.obj/Mem_Map.o .shobj/Mem_Map.so: Mem_Map.cpp \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.i +.obj/Memory_Pool.o .shobj/Memory_Pool.so: Memory_Pool.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Memory_Pool.i +.obj/Message_Block.o .shobj/Message_Block.so: Message_Block.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Message_Block.i +.obj/Method_Object.o .shobj/Method_Object.so: Method_Object.cpp \ + $(WRAPPER_ROOT)/ace/Method_Object.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h +.obj/Name_Proxy.o .shobj/Name_Proxy.so: Name_Proxy.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Name_Proxy.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Name_Request_Reply.h \ + $(WRAPPER_ROOT)/ace/SString.h +.obj/Name_Request_Reply.o .shobj/Name_Request_Reply.so: Name_Request_Reply.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Name_Request_Reply.h \ + $(WRAPPER_ROOT)/ace/SString.h +.obj/Name_Space.o .shobj/Name_Space.so: Name_Space.cpp \ + $(WRAPPER_ROOT)/ace/Name_Space.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/SString.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Name_Proxy.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Name_Request_Reply.h +.obj/Naming_Context.o .shobj/Naming_Context.so: Naming_Context.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Get_Opt.h \ + $(WRAPPER_ROOT)/ace/Naming_Context.h \ + $(WRAPPER_ROOT)/ace/SString.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Name_Proxy.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Name_Request_Reply.h \ + $(WRAPPER_ROOT)/ace/Name_Space.h \ + $(WRAPPER_ROOT)/ace/Remote_Name_Space.h \ + $(WRAPPER_ROOT)/ace/Local_Name_Space.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.cpp \ + $(WRAPPER_ROOT)/ace/Map_Manager.i \ + $(WRAPPER_ROOT)/ace/Local_Name_Space_T.h \ + $(WRAPPER_ROOT)/ace/Local_Name_Space_T.cpp +.obj/Obstack.o .shobj/Obstack.so: Obstack.cpp \ + $(WRAPPER_ROOT)/ace/Obstack.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i +.obj/OS.o .shobj/OS.so: OS.cpp \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/ARGV.h \ + $(WRAPPER_ROOT)/ace/OS.i +.obj/Parse_Node.o .shobj/Parse_Node.so: Parse_Node.cpp \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Service_Repository.h \ + $(WRAPPER_ROOT)/ace/Service_Record.h \ + $(WRAPPER_ROOT)/ace/Stream.h \ + $(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \ + $(WRAPPER_ROOT)/ace/Module.h \ + $(WRAPPER_ROOT)/ace/Task.h \ + $(WRAPPER_ROOT)/ace/Message_Queue.h \ + $(WRAPPER_ROOT)/ace/Message_Queue.cpp \ + $(WRAPPER_ROOT)/ace/Message_Queue.i \ + $(WRAPPER_ROOT)/ace/Task.cpp \ + $(WRAPPER_ROOT)/ace/Task.i \ + $(WRAPPER_ROOT)/ace/Module.cpp \ + $(WRAPPER_ROOT)/ace/Stream_Modules.h \ + $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \ + $(WRAPPER_ROOT)/ace/Stream_Modules.i \ + $(WRAPPER_ROOT)/ace/Module.i \ + $(WRAPPER_ROOT)/ace/Stream.cpp \ + $(WRAPPER_ROOT)/ace/Stream.i \ + $(WRAPPER_ROOT)/ace/Parse_Node.h \ + $(WRAPPER_ROOT)/ace/Parse_Node.i +.obj/Pipe.o .shobj/Pipe.so: Pipe.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i +.obj/Proactor.o .shobj/Proactor.so: Proactor.cpp \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/Proactor.i +.obj/Process.o .shobj/Process.so: Process.cpp \ + $(WRAPPER_ROOT)/ace/Process.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ARGV.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Svc_Handler.h \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Task.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Message_Queue.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/IO_Cntl_Msg.h \ + $(WRAPPER_ROOT)/ace/Message_Queue.cpp \ + $(WRAPPER_ROOT)/ace/Message_Queue.i \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Task.cpp \ + $(WRAPPER_ROOT)/ace/Module.h \ + $(WRAPPER_ROOT)/ace/Module.cpp \ + $(WRAPPER_ROOT)/ace/Stream_Modules.h \ + $(WRAPPER_ROOT)/ace/Stream_Modules.cpp \ + $(WRAPPER_ROOT)/ace/Stream_Modules.i \ + $(WRAPPER_ROOT)/ace/Module.i \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Task.i \ + $(WRAPPER_ROOT)/ace/Svc_Handler.cpp \ + $(WRAPPER_ROOT)/ace/Dynamic.h \ + $(WRAPPER_ROOT)/ace/Svc_Handler.i \ + $(WRAPPER_ROOT)/ace/Acceptor.h \ + $(WRAPPER_ROOT)/ace/Strategies.h \ + $(WRAPPER_ROOT)/ace/Strategies.cpp \ + $(WRAPPER_ROOT)/ace/Acceptor.i \ + $(WRAPPER_ROOT)/ace/Acceptor.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/ace/Process.i +.obj/Process_Manager.o .shobj/Process_Manager.so: Process_Manager.cpp +.obj/Profile_Timer.o .shobj/Profile_Timer.so: Profile_Timer.cpp \ + $(WRAPPER_ROOT)/ace/Profile_Timer.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Profile_Timer.i +.obj/Reactor.o .shobj/Reactor.so: Reactor.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/Reactor.i +.obj/ReactorEx.o .shobj/ReactorEx.so: ReactorEx.cpp \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/Token.h +.obj/Read_Buffer.o .shobj/Read_Buffer.so: Read_Buffer.cpp \ + $(WRAPPER_ROOT)/ace/Read_Buffer.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Read_Buffer.i \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h +.obj/Remote_Name_Space.o .shobj/Remote_Name_Space.so: Remote_Name_Space.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Remote_Name_Space.h \ + $(WRAPPER_ROOT)/ace/SString.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Name_Proxy.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Name_Request_Reply.h \ + $(WRAPPER_ROOT)/ace/Name_Space.h +.obj/Remote_Tokens.o .shobj/Remote_Tokens.so: Remote_Tokens.cpp \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Remote_Tokens.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Synch_Options.h \ + $(WRAPPER_ROOT)/ace/Local_Tokens.h \ + $(WRAPPER_ROOT)/ace/Synch.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.h \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Simple.i \ + $(WRAPPER_ROOT)/ace/SV_Semaphore_Complex.i \ + $(WRAPPER_ROOT)/ace/Synch_T.h \ + $(WRAPPER_ROOT)/ace/Synch_T.cpp \ + $(WRAPPER_ROOT)/ace/Thread.h \ + $(WRAPPER_ROOT)/ace/Synch_T.i \ + $(WRAPPER_ROOT)/ace/Stack.h \ + $(WRAPPER_ROOT)/ace/Stack.cpp \ + $(WRAPPER_ROOT)/ace/Stack.i \ + $(WRAPPER_ROOT)/ace/Map_Manager.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.cpp \ + $(WRAPPER_ROOT)/ace/Malloc.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.h \ + $(WRAPPER_ROOT)/ace/Malloc_T.cpp \ + $(WRAPPER_ROOT)/ace/Malloc_T.i \ + $(WRAPPER_ROOT)/ace/Memory_Pool.h \ + $(WRAPPER_ROOT)/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/ace/Signal.h \ + $(WRAPPER_ROOT)/ace/Set.h \ + $(WRAPPER_ROOT)/ace/Set.cpp \ + $(WRAPPER_ROOT)/ace/Set.i \ + $(WRAPPER_ROOT)/ace/Mem_Map.h \ + $(WRAPPER_ROOT)/ace/Service_Config.h \ + $(WRAPPER_ROOT)/ace/Service_Object.h \ + $(WRAPPER_ROOT)/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/ace/Proactor.h \ + $(WRAPPER_ROOT)/ace/Message_Block.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/ace/ReactorEx.h \ + $(WRAPPER_ROOT)/ace/Token.h \ + $(WRAPPER_ROOT)/ace/Reactor.h \ + $(WRAPPER_ROOT)/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/ace/Pipe.h \ + $(WRAPPER_ROOT)/ace/Pipe.i \ + $(WRAPPER_ROOT)/ace/Reactor.i \ + $(WRAPPER_ROOT)/ace/Svc_Conf_Tokens.h \ + $(WRAPPER_ROOT)/ace/Map_Manager.i \ + $(WRAPPER_ROOT)/ace/Token_Request_Reply.h \ + $(WRAPPER_ROOT)/ace/Singleton.h \ + $(WRAPPER_ROOT)/ace/Singleton.cpp \ + $(WRAPPER_ROOT)/ace/Singleton.i \ + $(WRAPPER_ROOT)/ace/Remote_Tokens.i +.obj/SOCK.o .shobj/SOCK.so: SOCK.cpp \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i +.obj/SOCK_Acceptor.o .shobj/SOCK_Acceptor.so: SOCK_Acceptor.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Acceptor.i +.obj/SOCK_CODgram.o .shobj/SOCK_CODgram.so: SOCK_CODgram.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_CODgram.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/SOCK_CODgram.i +.obj/SOCK_Connector.o .shobj/SOCK_Connector.so: SOCK_Connector.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/ace/Handle_Set.h +.obj/SOCK_Dgram.o .shobj/SOCK_Dgram.so: SOCK_Dgram.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.i +.obj/SOCK_Dgram_Bcast.o .shobj/SOCK_Dgram_Bcast.so: SOCK_Dgram_Bcast.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram_Bcast.h \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram_Bcast.i +.obj/SOCK_IO.o .shobj/SOCK_IO.so: SOCK_IO.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_IO.i +.obj/SOCK_Dgram_Mcast.o .shobj/SOCK_Dgram_Mcast.so: SOCK_Dgram_Mcast.cpp \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram_Mcast.h \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/ace/SOCK.h \ + $(WRAPPER_ROOT)/ace/ACE.h \ + $(WRAPPER_ROOT)/ace/OS.h \ + $(WRAPPER_ROOT)/ace/Time_Value.h \ + $(WRAPPER_ROOT)/ace/config.h \ + $(WRAPPER_ROOT)/ace/Trace.h \ + $(WRAPPER_ROOT)/ace/ACE.i \ + $(WRAPPER_ROOT)/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/ace/Log_Record.h \ + $(WRAPPER_ROOT)/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/ace/Log_Record.i \ + $(WRAPPER_ROOT)/ace/Addr.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/ace/SOCK.i \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/ace/SOCK_Dgram_Mcast.i +.obj/SOCK_Stream.o .shobj/SOCK_Stream.so: SOCK_Stream.cpp \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Version.h \ + $(ACE_ROOT)/ace/Typed_SV_Message.i +.obj/Typed_SV_Message_Queue.o .shobj/Typed_SV_Message_Queue.so: Typed_SV_Message_Queue.cpp \ +.obj/Typed_SV_Message_Queue.o .shobj/Typed_SV_Message_Queue.so: Typed_SV_Message_Queue.cpp \ + $(ACE_ROOT)/ace/Typed_SV_Message.cpp + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/iosfwd.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Version.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Typed_SV_Message.i \ + $(ACE_ROOT)/ace/Typed_SV_Message.i \ + $(ACE_ROOT)/ace/Typed_SV_Message.cpp \ + $(ACE_ROOT)/ace/Typed_SV_Message_Queue.h \ + $(ACE_ROOT)/ace/SV_Message.i \ + $(ACE_ROOT)/ace/Typed_SV_Message_Queue.i + $(ACE_ROOT)/ace/Typed_SV_Message_Queue.i + $(ACE_ROOT)/ace/Typed_SV_Message_Queue.i \ + $(ACE_ROOT)/ace/Typed_SV_Message_Queue.cpp diff --git a/ace/Malloc.cpp b/ace/Malloc.cpp new file mode 100644 index 00000000000..734827dc9b6 --- /dev/null +++ b/ace/Malloc.cpp @@ -0,0 +1,81 @@ +// Malloc.cpp +// $Id$ + +#if !defined (ACE_MALLOC_C) +#define ACE_MALLOC_C + +#define ACE_BUILD_DLL +#include "ace/Malloc.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Malloc.i" +#endif /* __ACE_INLINE__ */ + +void +ACE_Control_Block::dump (void) const +{ + ACE_TRACE ("ACE_Control_Block::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->name_head_->dump (); + ACE_DEBUG ((LM_DEBUG, "freep_ = %x", this->freep_)); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Name_Node::ACE_Name_Node (void) +{ + ACE_TRACE ("ACE_Name_Node::ACE_Name_Node"); +} + +ACE_Name_Node::ACE_Name_Node (const char *name, + void *ptr, + ACE_Name_Node *next) + : pointer_ (ptr), + next_ (next) +{ + ACE_TRACE ("ACE_Name_Node::ACE_Name_Node"); + ACE_OS::strcpy (this->name_, name); +} + +void +ACE_Name_Node::dump (void) const +{ + ACE_TRACE ("ACE_Name_Node"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "pointer = %x", this->pointer_)); + ACE_DEBUG ((LM_DEBUG, "\nnext_ = %x", this->next_)); + ACE_DEBUG ((LM_DEBUG, "\nname_ = %s", this->name_)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_MALLOC_STATS) +ACE_Malloc_Stats::ACE_Malloc_Stats (void) + : nblocks_ (0), + nchunks_ (0), + ninuse_ (0) +{ + ACE_TRACE ("ACE_Malloc_Stats::ACE_Malloc_Stats"); +} + +void +ACE_Malloc_Stats::dump (void) const +{ + ACE_TRACE ("ACE_Malloc_Stats::print"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + int nblocks = this->nblocks_; + int ninuse = this->ninuse_; + int nchunks = this->nchunks_; + + ACE_DEBUG ((LM_DEBUG, "nblocks = %d", nblocks)); + ACE_DEBUG ((LM_DEBUG, "\nninuse = %d", ninuse)); + ACE_DEBUG ((LM_DEBUG, "\nnchunks = %d", nchunks)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#endif /* ACE_MALLOC_STATS */ +#endif /* ACE_MALLOC_C */ diff --git a/ace/Malloc.h b/ace/Malloc.h new file mode 100644 index 00000000000..fe67fca2150 --- /dev/null +++ b/ace/Malloc.h @@ -0,0 +1,217 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Malloc.h +// +// = AUTHOR +// Doug Schmidt and Irfan Pyarali +// +// ============================================================================ + +#if !defined (ACE_MALLOC_H) +#define ACE_MALLOC_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Allocator + // = TITLE + // Interface for a dynamic memory allocator that uses inheritance + // and dynamic binding to provide extensible mechanisms for + // allocating and deallocating memory. +{ +public: + // = Memory Management + + virtual void *malloc (size_t nbytes) = 0; + // Allocate <nbytes>, but don't give them any initial value. + + virtual void *calloc (size_t nbytes, char initial_value = '\0') = 0; + // Allocate <nbytes>, giving them <initial_value>. + + virtual void free (void *ptr) = 0; + // Free <ptr> (must have been allocated by <ACE_Allocator::malloc>). + + virtual int remove (void) = 0; + // Remove any resources associated with this memory manager. + + // = Map manager like functions + + virtual int bind (const char *name, void *pointer, int duplicates = 0) = 0; + // Associate <name> with <pointer>. If <duplicates> == 0 then do + // not allow duplicate <name>/<pointer> associations, else if + // <duplicates> != 0 then allow duplicate <name>/<pointer> + // assocations. Returns 0 if successfully binds (1) a previously + // unbound <name> or (2) <duplicates> != 0, returns 1 if trying to + // bind a previously bound <name> and <duplicates> == 0, else + // returns -1 if a resource failure occurs. + + virtual int trybind (const char *name, void *&pointer) = 0; + // Associate <name> with <pointer>. Does not allow duplicate + // <name>/<pointer> associations. Returns 0 if successfully binds + // (1) a previously unbound <name>, 1 if trying to bind a previously + // bound <name>, or returns -1 if a resource failure occurs. When + // this call returns <pointer>'s value will always reference the + // void * that <name> is associated with. Thus, if the caller needs + // to use <pointer> (e.g., to free it) a copy must be maintained by + // the caller. + + virtual int find (const char *name, void *&pointer) = 0; + // Locate <name> and pass out parameter via pointer. If found, + // return 0, Returns -1 if failure occurs. + + virtual int find (const char *name) = 0; + // returns 0 if the name is in the mapping. -1, otherwise. + + virtual int unbind (const char *name) = 0; + // Unbind (remove) the name from the map. Don't return the pointer + // to the caller + + virtual int unbind (const char *name, void *&pointer) = 0; + // Break any association of name. Returns the value of pointer in + // case the caller needs to deallocate memory. + + // = Protection and "sync" (i.e., flushing memory to persistent + // backing store). + + virtual int sync (ssize_t len = -1, int flags = MS_SYNC) = 0; + // Sync <len> bytes of the memory region to the backing store + // starting at <this->base_addr_>. If <len> == -1 then sync the + // whole region. + + virtual int sync (void *addr, size_t len, int flags = MS_SYNC) = 0; + // Sync <len> bytes of the memory region to the backing store + // starting at <addr_>. + + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR) = 0; + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR) = 0; + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + virtual void dump (void) const = 0; + // Dump the state of the object. +}; + +typedef long ACE_Malloc_Align; +// For alignment to long boundary + +union ACE_Export ACE_Malloc_Header +// TITLE +// This is a block header. +{ + struct ACE_Malloc_Control_Block + { + ACE_Malloc_Header *next_block_; + // Points to next block if on free list. + size_t size_; + // Size of this block. + } s_; + + ACE_Malloc_Align x_; + // Force alignment. +}; + +class ACE_Export ACE_Name_Node + // = TITLE + // This is stored as a linked list within the Memory_Pool + // to allow "named memory chunks." +{ +public: + // = Initialization methods. + ACE_Name_Node (const char *name, void *, ACE_Name_Node *); + ACE_Name_Node (void); + + char *name_; + // Name of the Node. + + void *pointer_; + // Pointer to the contents. + + ACE_Name_Node *next_; + // Pointer to the next node in the chain. + + void dump (void) const; + // Dump the state of the object. +}; + +class ACE_Export ACE_Control_Block + // = TITLE + // This information is stored in memory allocated by the MEMORY_POOL. + // + // = DESCRIPTION + // This class should be local to class ACE_Malloc, but cfront and + // G++ don't like nested classes in templates... +{ +public: + ACE_Name_Node *name_head_; + // Head of the linked list of Name Nodes. + + ACE_Malloc_Header *freep_; + // Current head of the freelist. + + char lock_name_[MAXNAMELEN]; + // Name of lock thats ensures mutual exclusion. + +#if defined (ACE_MALLOC_STATS) + // Keep statistics about ACE_Malloc state and performance. + ACE_Malloc_Stats malloc_stats_; +#endif /* ACE_MALLOC_STATS */ + + ACE_Malloc_Header base_; + // Dummy node used to anchor the freelist. + + void dump (void) const; + // Dump the state of the object. +}; + +#if defined (ACE_MALLOC_STATS) +#include "ace/Sync_T.h" +#if defined (ACE_HAS_THREADS) +#define ACE_PROCESS_MUTEX ACE_Process_Mutex +#else +#include "ace/SV_Semaphore_Simple.h" +#define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple +#endif /* ACE_HAS_THREADS */ + +typedef ACE_Atomic_Op<ACE_PROCESS_MUTEX, int> ACE_INT; + +struct ACE_Export ACE_Malloc_Stats +// TITLE +// This keeps stats on the usage of the memory manager. +{ + ACE_Malloc_Stats (void); + void dump (void) const; + + ACE_INT nchunks_; + // Coarse-grained unit of allocation. + + ACE_INT nblocks_; + // Fine-grained unit of allocation. + + ACE_INT ninuse_; + // Number of blocks in use +}; +#define AMS(X) X +#else +#define AMS(X) +#endif /* ACE_MALLOC_STATS */ + +#if defined (__ACE_INLINE__) +#include "ace/Malloc.i" +#endif /* __ACE_INLINE__ */ + +// Include the ACE_Malloc templates and ACE_Memory_Pool stuff at this point. +#include "ace/Malloc_T.h" +#include "ace/Memory_Pool.h" + +#endif /* ACE_MALLOC_H */ diff --git a/ace/Malloc.i b/ace/Malloc.i new file mode 100644 index 00000000000..ae0bc8064d4 --- /dev/null +++ b/ace/Malloc.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Malloc.i diff --git a/ace/Malloc_T.cpp b/ace/Malloc_T.cpp new file mode 100644 index 00000000000..52390601baa --- /dev/null +++ b/ace/Malloc_T.cpp @@ -0,0 +1,574 @@ +// Malloc_T.cpp +// $Id$ + +#if !defined (ACE_MALLOC_T_C) +#define ACE_MALLOC_T_C + +#define ACE_BUILD_DLL +#include "ace/Malloc_T.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Malloc_T.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Malloc) + +template <class MALLOC> +ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (const char *pool_name, + const char *lock_name) + : allocator_ (pool_name, lock_name) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter"); +} + +template <class MALLOC> +ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (const char *pool_name) + : allocator_ (pool_name) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter"); +} + +template <class MALLOC> void +ACE_Allocator_Adapter<MALLOC>::dump (void) const +{ + ACE_TRACE ("ACE_Malloc<MALLOC>::dump"); + this->allocator_.dump (); +} + +template <class MEM_POOL, class LOCK> void +ACE_Malloc<MEM_POOL, LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->memory_pool_.dump (); + ACE_DEBUG ((LM_DEBUG, "cb_ptr_ = %x", this->cb_ptr_)); + ACE_DEBUG ((LM_DEBUG, "\n")); +#if defined (ACE_MALLOC_STATS) + this->malloc_stats_.dump (); +#endif /* ACE_MALLOC_STATS */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_MALLOC_STATS) + +template <class MEM_POOL, class LOCK> void +ACE_Malloc<MEM_POOL, LOCK>::print_stats (void) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::print_stats"); + ACE_GUARD (LOCK, ace_mon, this->lock_); + + this->cb_ptr_->malloc_stats_.print (); + ACE_DEBUG ((LM_DEBUG, "(%P|%t) contents of freelist:\n")); + + for (ACE_Malloc_Header *currp = this->cb_ptr_->freep_->s_.next_block_; + ; + currp = currp->s_.next_block_) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) ptr = %u, ACE_Malloc_Header units = %d, byte units = %d\n", + currp, currp->s_.size_, + currp->s_.size_ * sizeof (ACE_Malloc_Header))); + if (currp == this->cb_ptr_->freep_) + break; + } +} +#endif /* ACE_MALLOC_STATS */ + +// Put block AP in the free list (locked version). + +template<class MEM_POOL, class LOCK> void +ACE_Malloc<MEM_POOL, LOCK>::free (void *ap) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::free"); + ACE_GUARD (LOCK, ace_mon, this->lock_); + + this->shared_free (ap); +} + +// This function is called by the ACE_Malloc constructor to initialize +// the memory pool. The first time in it allocates room for the +// control block (as well as a chunk of memory, depending on +// rounding...). Depending on the type of <MEM_POOL> (i.e., shared +// vs. local) subsequent calls from other processes will only +// initialize the control block pointer. + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::open (void) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::open"); + ACE_GUARD_RETURN (LOCK, ace_mon, this->lock_, -1); + + size_t rounded_bytes = 0; + int first_time = 0; + + this->cb_ptr_ = (ACE_Control_Block *) + this->memory_pool_.init_acquire (sizeof *this->cb_ptr_, + rounded_bytes, + first_time); + if (this->cb_ptr_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "init_acquire failed"), -1); + else if (first_time) + { + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) first time in, control block = %u\n", this->cb_ptr_)); + +#if defined (ACE_MALLOC_STATS) + // Call the constructor on the LOCK, using the placement + // operator! + new ((void *) &this->cb_ptr_->malloc_stats_) ACE_Malloc_Stats; +#endif /* ACE_MALLOC_STATS */ + + // Initialize the freelist pointer to point to the dummy + // ACE_Malloc_Header. + this->cb_ptr_->freep_ = &this->cb_ptr_->base_; + + // Initialize the dummy ACE_Malloc_Header to point to itself. + this->cb_ptr_->freep_->s_.size_ = 0; + this->cb_ptr_->freep_->s_.next_block_ = this->cb_ptr_->freep_; + + // initialize the name list to 0 + this->cb_ptr_->name_head_ = 0; + + + if (rounded_bytes > (sizeof *this->cb_ptr_ + sizeof (ACE_Malloc_Header))) + { + // If we've got any extra space at the end of the control + // block, then skip past the dummy ACE_Malloc_Header to + // point at the first free block. + ACE_Malloc_Header *p = this->cb_ptr_->freep_ + 1; + p->s_.size_ = (rounded_bytes - sizeof *this->cb_ptr_) + / sizeof (ACE_Malloc_Header); + + AMS (++this->cb_ptr_->malloc_stats_.nchunks_); + AMS (++this->cb_ptr_->malloc_stats_.nblocks_); + AMS (++this->cb_ptr_->malloc_stats_.ninuse_); + + // Insert the newly allocated chunk of memory into the free + // list. + this->shared_free ((void *) (p + 1)); + } + } + return 0; +} + +template <class MEM_POOL, class LOCK> +ACE_Malloc<MEM_POOL, LOCK>::ACE_Malloc (const char *pool_name) + : memory_pool_ (pool_name), + lock_ (pool_name == 0 ? 0 : ACE::basename (pool_name, + ACE_DIRECTORY_SEPARATOR_CHAR)) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::ACE_Malloc"); + + this->open (); +} + +template <class MEM_POOL, class LOCK> +ACE_Malloc<MEM_POOL, LOCK>::ACE_Malloc (const char *pool_name, + const char *lock_name) + : memory_pool_ (pool_name), + lock_ (lock_name) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::ACE_Malloc"); + + this->open (); +} + +// Clean up the resources allocated by ACE_Malloc. + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::remove (void) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::remove"); + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) destroying ACE_Malloc\n")); + int result = 0; + +#if defined (ACE_MALLOC_STATS) + this->print_stats (); +#endif /* ACE_MALLOC_STATS */ + + // Remove the LOCK. + this->lock_.remove (); + + // Give the memory pool a chance to release its resources. + result = this->memory_pool_.release (); + + return result; +} + +// General-purpose memory allocator. Assumes caller holds the locks. + +template <class MEM_POOL, class LOCK> void * +ACE_Malloc<MEM_POOL, LOCK>::shared_malloc (size_t nbytes) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::shared_malloc"); + + // Round up request to a multiple of the ACE_Malloc_Header size. + size_t nunits = (nbytes + sizeof (ACE_Malloc_Header) - 1) + / sizeof (ACE_Malloc_Header) + 1; + + // Begin the search starting at the place in the freelist + // where the last block was found. + ACE_Malloc_Header *prevp = this->cb_ptr_->freep_; + ACE_Malloc_Header *currp = prevp->s_.next_block_; + + // Search the freelist to locate a block of the appropriate size. + + for (int i = 0; ; i++, prevp = currp, currp = currp->s_.next_block_) + { + if (currp->s_.size_ >= nunits) // Big enough + { + AMS (++this->cb_ptr_->malloc_stats_.ninuse_); + if (currp->s_.size_ == nunits) + // Exact size, just update the pointers. + prevp->s_.next_block_ = currp->s_.next_block_; + else + { + // Remaining chunk is larger than requested block, so + // allocate at tail end. + AMS (++this->cb_ptr_->malloc_stats_.nblocks_); + currp->s_.size_ -= nunits; + currp += currp->s_.size_; + currp->s_.size_ = nunits; + } + this->cb_ptr_->freep_ = prevp; + // Skip over the ACE_Malloc_Header when returning pointer. + return (void *) (currp + 1); + } + else if (currp == this->cb_ptr_->freep_) + { + // We've wrapped around freelist without finding a block. + // Therefore, we need to ask the memory pool for a new chunk + // of bytes. + + size_t chunk_bytes = 0; + + if ((currp = (ACE_Malloc_Header *) + this->memory_pool_.acquire (nunits * sizeof (ACE_Malloc_Header), + chunk_bytes)) != 0) + { + AMS (++this->cb_ptr_->malloc_stats_.nblocks_); + AMS (++this->cb_ptr_->malloc_stats_.nchunks_); + AMS (++this->cb_ptr_->malloc_stats_.ninuse_); + + // Compute the chunk size in ACE_Malloc_Header units. + currp->s_.size_ = chunk_bytes / sizeof (ACE_Malloc_Header); + + // Insert the new chunk into the freelist. + this->shared_free ((void *) (currp + 1)); + currp = this->cb_ptr_->freep_; + } + else + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "malloc"), 0); + } + } +} + +// General-purpose memory allocator. + +template <class MEM_POOL, class LOCK> void * +ACE_Malloc<MEM_POOL, LOCK>::malloc (size_t nbytes) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::malloc"); + ACE_GUARD_RETURN (LOCK, ace_mon, this->lock_, 0); + + return this->shared_malloc (nbytes); +} + +// General-purpose memory allocator. + +template <class MEM_POOL, class LOCK> void * +ACE_Malloc<MEM_POOL, LOCK>::calloc (size_t nbytes, + char initial_value) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::calloc"); + void *ptr = this->malloc (nbytes); + + if (ptr != 0) + ACE_OS::memset (ptr, initial_value, nbytes); + + return ptr; +} + +// Put block AP in the free list (must be called with locks held!) + +template <class MEM_POOL, class LOCK> void +ACE_Malloc<MEM_POOL, LOCK>::shared_free (void *ap) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::shared_free"); + + if (ap == 0) + return; + + ACE_Malloc_Header *blockp; // Points to the block ACE_Malloc_Header. + ACE_Malloc_Header *currp; + + // Adjust AP to point to the block ACE_Malloc_Header + blockp = (ACE_Malloc_Header *) ap - 1; + + // Search until we find the location where the blocks belongs. Note + // that addresses are kept in sorted order. + + for (currp = this->cb_ptr_->freep_; + blockp <= currp || blockp >= currp->s_.next_block_; + currp = currp->s_.next_block_) + { + if (currp >= currp->s_.next_block_ + && (blockp > currp || blockp < currp->s_.next_block_)) + // Freed block at the start or the end of the memory pool + break; + } + + // Join to upper neighbor + if (blockp + blockp->s_.size_ == currp->s_.next_block_) + { + AMS (--this->cb_ptr_->malloc_stats_.nblocks_); + blockp->s_.size_ += currp->s_.next_block_->s_.size_; + blockp->s_.next_block_ = currp->s_.next_block_->s_.next_block_; + } + else + blockp->s_.next_block_ = currp->s_.next_block_; + + if (currp + currp->s_.size_ == blockp) // Join to lower neighbor + { + AMS (--this->cb_ptr_->malloc_stats_.nblocks_); + currp->s_.size_ += blockp->s_.size_; + currp->s_.next_block_ = blockp->s_.next_block_; + } + else + currp->s_.next_block_ = blockp; + + AMS (--this->cb_ptr_->malloc_stats_.ninuse_); + this->cb_ptr_->freep_ = currp; +} + +// No locks held here, caller must acquire/release lock. + +template <class MEM_POOL, class LOCK> ACE_Name_Node * +ACE_Malloc<MEM_POOL, LOCK>::shared_find (const char *name) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::shared_find"); + + for (ACE_Name_Node *node = this->cb_ptr_->name_head_; + node != 0; + node = node->next_) + if (ACE_OS::strcmp (node->name_, name) == 0) + return node; + + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::shared_bind (const char *name, + void *pointer) +{ + // Combine the two allocations into one to avoid overhead... + ACE_Name_Node *new_node = (ACE_Name_Node *) + this->shared_malloc (sizeof (ACE_Name_Node) + ACE_OS::strlen (name) + 1); + + if (new_node == 0) + return -1; + + // This is a sleezy trick ;-) + new_node->name_ = (char *) (new_node + 1); + + // Insert new node at the head of the list. Note that (new_node) is + // *not* a cast! + ACE_NEW_RETURN (this->cb_ptr_->name_head_, + (new_node) ACE_Name_Node (name, pointer, + this->cb_ptr_->name_head_), + -1); + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::trybind (const char *name, + void *&pointer) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::trybind"); + ACE_Write_Guard<LOCK> mon (this->lock_); + + ACE_Name_Node *node = this->shared_find (name); + if (node == 0) + // Didn't find it, so insert it. + return this->shared_bind (name, pointer); + else + { + // Found it, so return a copy of the current entry. + pointer = node->pointer_; + return 1; + } +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::bind (const char *name, + void *pointer, + int duplicates) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::bind"); + ACE_Write_Guard<LOCK> mon (this->lock_); + + if (duplicates == 0 && this->shared_find (name) != 0) + // If we're not allowing duplicates, then if the name is already + // present, return 1. + return 1; + else + // If we get this far, either we're allowing duplicates or we didn't + // find the name yet. + + return this->shared_bind (name, pointer); +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::find (const char *name, void *&pointer) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::find"); + + ACE_Read_Guard<LOCK> mon (this->lock_); + + ACE_Name_Node *node = this->shared_find (name); + + if (node == 0) + return -1; + else + { + pointer = node->pointer_; + return 0; + } +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::find (const char *name) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::find"); + + ACE_Read_Guard<LOCK> mon (this->lock_); + return this->shared_find (name) == 0 ? -1 : 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::unbind (const char *name, void *&pointer) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::unbind"); + + ACE_Write_Guard<LOCK> mon (this->lock_); + ACE_Name_Node *prev = 0; + + for (ACE_Name_Node *curr = this->cb_ptr_->name_head_; + curr != 0; + curr = curr->next_) + { + if (ACE_OS::strcmp (curr->name_, name) == 0) + { + pointer = curr->pointer_; + + if (prev == 0) + this->cb_ptr_->name_head_ = curr->next_; + else + prev->next_ = curr->next_; + + // This will free up both the node and the name due to our + // sleezy trick in bind()! + this->shared_free (curr); + return 0; + } + prev = curr; + } + + // Didn't find it, so fail. + return -1; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::unbind (const char *name) +{ + ACE_TRACE ("ACE_Malloc<MEM_POOL, LOCK>::unbind"); + void *temp = 0; + return this->unbind (name, temp); +} + + +template <class MEM_POOL, class LOCK> void +ACE_Malloc_Iterator<MEM_POOL, LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Malloc_Iterator<MEM_POOL, LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->curr_->dump (); + this->guard_.dump (); + ACE_DEBUG ((LM_DEBUG, "name_ = %s", this->name_)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class MEM_POOL, class LOCK> +ACE_Malloc_Iterator<MEM_POOL, LOCK>::ACE_Malloc_Iterator (ACE_Malloc<MEM_POOL, LOCK> &malloc, + const char *name) + : malloc_ (malloc), + guard_ (malloc_.lock_), + curr_ (0), + name_ (name != 0 ? ACE_OS::strdup (name) : 0) +{ + ACE_TRACE ("ACE_Malloc_Iterator<MEM_POOL, LOCK>::ACE_Malloc_Iterator"); + // Cheap trick to make code simple. + ACE_Name_Node temp; + this->curr_ = &temp; + this->curr_->next_ = malloc_.cb_ptr_->name_head_; + + this->advance(); +} + +template <class MEM_POOL, class LOCK> +ACE_Malloc_Iterator<MEM_POOL, LOCK>::~ACE_Malloc_Iterator (void) +{ + ACE_OS::free ((void *) this->name_); +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc_Iterator<MEM_POOL, LOCK>::next (void *&next_entry, + char *&name) +{ + ACE_TRACE ("ACE_Malloc_Iterator<MEM_POOL, LOCK>::next"); + + if (curr_ != 0) + { + next_entry = curr_->pointer_; + name = curr_->name_; + return 1; + } + else + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc_Iterator<MEM_POOL, LOCK>::next (void *&next_entry) +{ + ACE_TRACE ("ACE_Malloc_Iterator<MEM_POOL, LOCK>::next"); + + if (curr_ != 0) + { + next_entry = curr_->pointer_; + return 1; + } + else + return 0; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc_Iterator<MEM_POOL, LOCK>::advance (void) +{ + ACE_TRACE ("ACE_Malloc_Iterator<MEM_POOL, LOCK>::advance"); + + this->curr_ = this->curr_->next_; + + if (this->name_ == 0) + return 1; + + for (; + this->curr_ != 0 && + ACE_OS::strcmp (this->name_, this->curr_->name_) != 0; + this->curr_ = this->curr_->next_) + continue; + return 1; +} + +#endif /* ACE_MALLOC_T_C */ diff --git a/ace/Malloc_T.h b/ace/Malloc_T.h new file mode 100644 index 00000000000..89434879f31 --- /dev/null +++ b/ace/Malloc_T.h @@ -0,0 +1,337 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Malloc_T.h +// +// = AUTHOR +// Doug Schmidt and Irfan Pyarali +// +// ============================================================================ + +#if !defined (ACE_MALLOC_T_H) +#define ACE_MALLOC_T_H + +#include "ace/ACE.h" +#include "ace/Log_Msg.h" +#include "ace/Synch.h" +#include "ace/Malloc.h" + +template <class MALLOC> +class ACE_Allocator_Adapter : public ACE_Allocator + // = TITLE + // This class is an Adapter that allows the <ACE_Allocator> to + // use the <Malloc> class below. +{ +public: + // Trait. + typedef MALLOC ALLOCATOR; + + // = Initialization. + ACE_Allocator_Adapter (const char *pool_name = ACE_DEFAULT_MUTEX); + ACE_Allocator_Adapter (const char *pool_name, + const char *lock_name); + // Constructor. + + // = Memory Management + + virtual void *malloc (size_t nbytes); + // Allocate <nbytes>, but don't give them any initial value. + + virtual void *calloc (size_t nbytes, char initial_value = '\0'); + // Allocate <nbytes>, giving them all an <initial_value>. + + virtual void free (void *ptr); + // Free <ptr> (must have been allocated by <ACE_Allocator::malloc>). + + virtual int remove (void); + // Remove any resources associated with this memory manager. + + // = Map manager like functions + + int bind (const char *name, void *pointer, int duplicates = 0); + // Associate <name> with <pointer>. If <duplicates> == 0 then do + // not allow duplicate <name>/<pointer> associations, else if + // <duplicates> != 0 then allow duplicate <name>/<pointer> + // assocations. Returns 0 if successfully binds (1) a previously + // unbound <name> or (2) <duplicates> != 0, returns 1 if trying to + // bind a previously bound <name> and <duplicates> == 0, else + // returns -1 if a resource failure occurs. + + int trybind (const char *name, void *&pointer); + // Associate <name> with <pointer>. Does not allow duplicate + // <name>/<pointer> associations. Returns 0 if successfully binds + // (1) a previously unbound <name>, 1 if trying to bind a previously + // bound <name>, or returns -1 if a resource failure occurs. When + // this call returns <pointer>'s value will always reference the + // void * that <name> is associated with. Thus, if the caller needs + // to use <pointer> (e.g., to free it) a copy must be maintained by + // the caller. + + int find (const char *name, void *&pointer); + // Locate <name> and pass out parameter via pointer. If found, + // return 0, Returns -1 if failure occurs. + + int find (const char *name); + // returns 0 if the name is in the mapping. -1, otherwise. + + int unbind (const char *name); + // Unbind (remove) the name from the map. Don't return the pointer + // to the caller + + int unbind (const char *name, void *&pointer); + // Break any association of name. Returns the value of pointer in + // case the caller needs to deallocate memory. + + // = Protection and "sync" (i.e., flushing data to backing store). + + int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <this->base_addr_>. If <len> == -1 then sync the + // whole region. + + int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <addr_>. + + int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + ALLOCATOR &allocator (void); + // Returns the underlying allocator. + + virtual void dump (void) const; + // Dump the state of the object. + +private: + ALLOCATOR allocator_; + // ALLOCATOR instance. +}; + +// Forward declaration. +template <class MEM_POOL, class LOCK> +class ACE_Malloc_Iterator; + +template <class MEM_POOL, class LOCK> +class ACE_Malloc + // = TITLE + // Define a C++ class that uses parameterized types to provide + // an extensible mechanism for encapsulating various of dynamic + // memory management strategies. + // + // = DESCRIPTION + // This class can be configured flexibly with different + // MEMORY_POOL strategies and different types of LOCK + // strategies. +{ +friend class ACE_Malloc_Iterator<MEM_POOL, LOCK>; +public: + typedef MEM_POOL MEMORY_POOL; + + // = Initialization and termination methods. + ACE_Malloc (const char *pool_name = 0); + // Initialize ACE_Malloc. This constructor passes <pool_name> to + // initialize the memory pool, and uses <ACE::basename> to + // automatically extract out the name used for the underlying lock + // name (if necessary). + + ACE_Malloc (const char *pool_name, + const char *lock_name); + // Initialize ACE_Malloc. This constructor passes <pool_name> to + // initialize the memory pool, and uses <lock_name> to automatically + // extract out the name used for the underlying lock name (if + // necessary). + + int remove (void); + // Releases resources allocated by ACE_Malloc. + + // = Memory management + + void *malloc (size_t nbytes); + // Allocate <nbytes>, but don't give them any initial value. + + void *calloc (size_t nbytes, char initial_value = '\0'); + // Allocate <nbytes>, giving them <initial_value>. + + void free (void *ptr); + // Deallocate memory pointed to by <ptr>, which must have been + // allocated previously by <this->malloc>. + + MEMORY_POOL &memory_pool (void); + // Returns a reference to the underlying memory pool. + + // = Map manager like functions + + int bind (const char *name, void *pointer, int duplicates = 0); + // Associate <name> with <pointer>. If <duplicates> == 0 then do + // not allow duplicate <name>/<pointer> associations, else if + // <duplicates> != 0 then allow duplicate <name>/<pointer> + // assocations. Returns 0 if successfully binds (1) a previously + // unbound <name> or (2) <duplicates> != 0, returns 1 if trying to + // bind a previously bound <name> and <duplicates> == 0, else + // returns -1 if a resource failure occurs. + + int trybind (const char *name, void *&pointer); + // Associate <name> with <pointer>. Does not allow duplicate + // <name>/<pointer> associations. Returns 0 if successfully binds + // (1) a previously unbound <name>, 1 if trying to bind a previously + // bound <name>, or returns -1 if a resource failure occurs. When + // this call returns <pointer>'s value will always reference the + // void * that <name> is associated with. Thus, if the caller needs + // to use <pointer> (e.g., to free it) a copy must be maintained by + // the caller. + + int find (const char *name, void *&pointer); + // Locate <name> and pass out parameter via <pointer>. If found, + // return 0, returns -1 if failure occurs. + + int find (const char *name); + // Returns 0 if <name> is in the mapping. -1, otherwise. + + int unbind (const char *name); + // Unbind (remove) the name from the map. Don't return the pointer + // to the caller. If you want to remove all occurrences of <name> + // you'll need to call this method multiple times until it fails... + + int unbind (const char *name, void *&pointer); + // Unbind (remove) one association of <name> to <pointer>. Returns + // the value of pointer in case the caller needs to deallocate + // memory. If you want to remove all occurrences of <name> you'll + // need to call this method multiple times until it fails... + + // = Protection and "sync" (i.e., flushing data to backing store). + + int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <this->base_addr_>. If <len> == -1 then sync the + // whole region. + + int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <addr_>. + + int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + +#if defined (ACE_MALLOC_STATS) + void print_stats (void); + // Dump statistics of how malloc is behaving. +#endif /* ACE_MALLOC_STATS */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int open (void); + // Initialize the Malloc pool. + + int shared_bind (const char *name, void *pointer); + // Associate <name> with <pointer>. Assumes that locks are held by + // callers. + + ACE_Name_Node *shared_find (const char *name); + // Try to locate <name>. If found, return the associated + // <ACE_Name_Node>, else returns 0 if can't find the <name>. + // Assumes that locks are held by callers. + + void *shared_malloc (size_t nbytes); + // Allocate memory. Assumes that locks are held by callers. + + void shared_free (void *ptr); + // Deallocate memory. Assumes that locks are held by callers. + + MEMORY_POOL memory_pool_; + // Pool of memory used by ACE_Malloc + + ACE_Control_Block *cb_ptr_; + // Pointer to the control block (stored in memory controlled by + // MEMORY_POOL). + + LOCK lock_; + // Local that ensures mutual exclusion. +}; + +template <class MEM_POOL, class LOCK> +class ACE_Malloc_Iterator + // = TITLE + // Iterator for names stored in Malloc'd memory. + // + // = DESCRIPTION + // Does not allows deletions while iteration is occurring. +{ +public: + // = Initialization method. + ACE_Malloc_Iterator (ACE_Malloc<MEM_POOL, LOCK> &malloc, const char *name = 0); + // if <name> = 0 it will iterate through everything else only + // through those entries whose <name> match + + ~ACE_Malloc_Iterator (void); + + // = Iteration methods. + + int next (void *&next_entry); + // Pass back the next <entry> in the set that hasn't yet been + // visited. Returns 0 when all items have been seen, else 1. + + int next (void *&next_entry, char *&name); + // Pass back the next <entry> (and the <name> associated with it) in + // the set that hasn't yet been visited. Returns 0 when all items + // have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Malloc<MEM_POOL, LOCK> &malloc_; + // Malloc we are iterating over. + + ACE_Name_Node *curr_; + // Keeps track of how far we've advanced... + + ACE_Read_Guard<LOCK> guard_; + // Lock Malloc for the lifetime of the iterator. + + const char *name_; + // Name that we are searching for. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Malloc_T.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Malloc_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Malloc_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_MALLOC_H */ diff --git a/ace/Malloc_T.i b/ace/Malloc_T.i new file mode 100644 index 00000000000..a66cb7ef7fd --- /dev/null +++ b/ace/Malloc_T.i @@ -0,0 +1,150 @@ +/* -*- C++ -*- */ +// $Id$ + +// Malloc_T.i + +template <class MALLOC> ACE_INLINE void * +ACE_Allocator_Adapter<MALLOC>::malloc (size_t nbytes) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::malloc"); + return this->allocator_.malloc (nbytes); +} + +template <class MALLOC> ACE_INLINE void * +ACE_Allocator_Adapter<MALLOC>::calloc (size_t nbytes, + char initial_value) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::malloc"); + return this->allocator_.calloc (nbytes, initial_value); +} + +template <class MALLOC> ACE_INLINE MALLOC & +ACE_Allocator_Adapter<MALLOC>::allocator (void) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::allocator"); + return this->allocator_; +} + +template <class MALLOC> ACE_INLINE void +ACE_Allocator_Adapter<MALLOC>::free (void *ptr) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::free"); + this->allocator_.free (ptr); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::remove (void) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::remove"); + return this->allocator_.remove (); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::trybind (const char *name, + void *&pointer) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::trybind"); + return this->allocator_.trybind (name, pointer); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::bind (const char *name, + void *pointer, + int duplicates) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::bind"); + return this->allocator_.bind (name, pointer, duplicates); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::find (const char *name, + void *&pointer) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find"); + return this->allocator_.find (name, pointer); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::find (const char *name) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find"); + return this->allocator_.find (name); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::unbind (const char *name, void *&pointer) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind"); + return this->allocator_.unbind (name, pointer); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::unbind (const char *name) +{ + ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind"); + return this->allocator_.unbind (name); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::sync (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::sync"); + return this->allocator_.sync (len, flags); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::sync (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::sync"); + return this->allocator_.sync (addr, len, flags); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::protect (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::protect"); + return this->allocator_.protect (len, flags); +} + +template <class MALLOC> ACE_INLINE int +ACE_Allocator_Adapter<MALLOC>::protect (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::protect"); + return this->allocator_.protect (addr, len, flags); +} + +template <class MEM_POOL, class LOCK> MEM_POOL & +ACE_Malloc<MEM_POOL, LOCK>::memory_pool (void) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::memory_pool"); + return this->memory_pool_; +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::sync (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::sync"); + return this->memory_pool_.sync (len, flags); +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::sync (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::sync"); + return this->memory_pool_.sync (addr, len, flags); +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::protect (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::protect"); + return this->memory_pool_.protect (len, flags); +} + +template <class MEM_POOL, class LOCK> int +ACE_Malloc<MEM_POOL, LOCK>::protect (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_Malloc<MEMORY_POOL, LOCK>::protect"); + return this->memory_pool_.protect (addr, len, flags); +} + diff --git a/ace/Map_Manager.cpp b/ace/Map_Manager.cpp new file mode 100644 index 00000000000..8a7794346bd --- /dev/null +++ b/ace/Map_Manager.cpp @@ -0,0 +1,575 @@ +// Map_Manager.cpp +// $Id$ + +#if !defined (ACE_MAP_MANAGER_C) +#define ACE_MAP_MANAGER_C + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Synch.h" +#include "ace/Malloc.h" +#include "ace/Service_Config.h" +#include "ace/Map_Manager.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Map_Manager.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Map_Entry) + +template <class EXT_ID, class INT_ID> void +ACE_Map_Entry<EXT_ID, INT_ID>::dump (void) const +{ + ACE_TRACE ("ACE_Map_Entry<EXT_ID, INT_ID>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "is_free_ = %d", this->is_free_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Map_Manager) + +template <class EXT_ID, class INT_ID, class LOCK> void +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "max_size_ = %d", this->max_size_)); + ACE_DEBUG ((LM_DEBUG, "\ncur_size_ = %d", this->cur_size_)); + this->allocator_->dump (); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class EXT_ID, class INT_ID, class LOCK> +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::ACE_Map_Manager (size_t size, + ACE_Allocator *allocator) + : allocator_ (0), + max_size_ (0), + cur_size_ (0), + search_structure_ (0) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::ACE_Map_Manager"); + + if (this->open (size, allocator) == -1) + ACE_ERROR ((LM_ERROR, "ACE_Map_Manager\n")); +} + +template <class EXT_ID, class INT_ID, class LOCK> +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::ACE_Map_Manager (ACE_Allocator *allocator) + : allocator_ (0), + max_size_ (0), + cur_size_ (0), + search_structure_ (0) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::ACE_Map_Manager"); + if (this->open (DEFAULT_SIZE, allocator) == -1) + ACE_ERROR ((LM_ERROR, "ACE_Map_Manager\n")); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::close_i (void) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::close_i"); + + if (this->search_structure_ != 0) + { + this->allocator_->free (this->search_structure_); + this->search_structure_ = 0; + } + return 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::close (void) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::close"); + ACE_Write_Guard<LOCK> m (this->lock_); + + return this->close_i (); +} + +template <class EXT_ID, class INT_ID, class LOCK> +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::~ACE_Map_Manager (void) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::~ACE_Map_Manager"); + this->close (); +} + +// Create a new search_structure of size SIZE. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::open (size_t size, + ACE_Allocator *allocator) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::open"); + ACE_Write_Guard<LOCK> m (this->lock_); + + if (allocator == 0) + allocator = ACE_Service_Config::allocator (); + + this->allocator_ = allocator; + + // If we need to grow buffer, then remove the existing buffer. + if (this->max_size_ < size) + return this->resize_i (size); + return 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::resize_i (size_t size) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::resize_i"); + + // If we need to grow buffer, then remove the existing buffer. + void *ptr = this->allocator_->malloc (size * sizeof (ACE_Map_Entry<EXT_ID, INT_ID>)); + + if (ptr == 0) + { + errno = ENOMEM; + return -1; + } + + size_t i; + + ACE_Map_Entry<EXT_ID, INT_ID> *temp = (ACE_Map_Entry<EXT_ID, INT_ID> *) ptr; + ACE_Map_Entry<EXT_ID, INT_ID> *foo; + + // Copy over the currently active elements. + for (i = 0; i < this->cur_size_; i++) + { + temp[i] = this->search_structure_[i]; // Structure assignment. + } + + this->max_size_ = size; + + // Mark the newly allocated elements as being "free". + + for (i = this->cur_size_; i < this->max_size_; i++) + { + // call the constructor for each element in the array + foo = new (&(temp[i])) ACE_Map_Entry<EXT_ID, INT_ID>; + temp[i].is_free_ = 1; + } + + this->allocator_->free (this->search_structure_); + + this->search_structure_ = temp; + return 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::shared_find (const EXT_ID &ext_id, + int &first_free) +{ + // See if the entry is already there, keeping track of the first + // free slot. + + for (size_t i = 0; i < this->cur_size_; i++) + { + ACE_Map_Entry<EXT_ID, INT_ID> &ss = this->search_structure_[i]; + + if (ss.is_free_ == 0) + { + if (ss.ext_id_ == ext_id) + return i; + } + else if (first_free == -1) + first_free = int (i); + } + + errno = ENOENT; + return -1; +} + +// Find the <int_id> corresponding to the <ext_id>. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::shared_find (const EXT_ID &ext_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::shared_find"); + + for (size_t i = 0; i < this->cur_size_; i++) + { + const ACE_Map_Entry<EXT_ID, INT_ID> &ss + = this->search_structure_[i]; + + if (ss.is_free_ == 0 && ss.ext_id_ == ext_id) + // We found it! + return i; + } + + // not found + errno = ENOENT; + return -1; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::shared_bind (const EXT_ID &ext_id, + const INT_ID &int_id, + int first_free) +{ + if (first_free > -1) + { + // We found a free spot, let's reuse it. + + ACE_Map_Entry<EXT_ID, INT_ID> &ss = this->search_structure_[first_free]; + + ss.ext_id_ = ext_id; + ss.int_id_ = int_id; + ss.is_free_ = 0; + this->allocator_->sync ((void *) &this->search_structure_[first_free], sizeof ss); + return 0; + } + + // Check if we have reached max_size_ + else if (this->cur_size_ == this->max_size_) + // We are out of room so grow the map + if (this->resize_i (this->max_size_ + DEFAULT_SIZE) == -1) + { + // Out of memory + errno = ENOMEM; + return -1; + } + + // Insert at the end of the active portion. + + ACE_Map_Entry<EXT_ID, INT_ID> &ss = this->search_structure_[this->cur_size_]; + + ss.int_id_ = int_id; + ss.ext_id_ = ext_id; + ss.is_free_ = 0; + this->allocator_->sync ((void *) &this->search_structure_[this->cur_size_], sizeof ss); + this->cur_size_++; + this->allocator_->sync ((void *) &this->cur_size_, sizeof this->cur_size_); + return 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::trybind_i (const EXT_ID &ext_id, + INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::trybind_i"); + int first_free = -1; + int index = this->shared_find (ext_id, first_free); + + if (index >= 0) + { + // There was already something there, so make a copy, but + // *don't* update anything in the map! + + int_id = this->search_structure_[index].int_id_; + return 1; + } + else + // We didn't find it, so let's bind it! + return this->shared_bind (ext_id, int_id, first_free); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::trybind (const EXT_ID &ext_id, + INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::trybind"); + ACE_Write_Guard<LOCK> m (this->lock_); + + return this->trybind_i (ext_id, int_id); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find_i (const EXT_ID &ext_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find_i"); + return this->shared_find (ext_id); +} + +// Find the INT_ID corresponding to the EXT_ID. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find (const EXT_ID &ext_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find"); + ACE_Read_Guard<LOCK> m (this->lock_); + + return this->find_i (ext_id); +} + +// Unbind (remove) the EXT_ID from the map and return it via an out +// parameter. Note that this method does *not* free up the INT_ID +// structure. Thus, if there is dynamic memory associated with this, +// the caller is responsible for freeing this memory. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind_i (const EXT_ID &ext_id, + INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind_i"); + + ssize_t index = this->shared_unbind (ext_id); + + if (index == -1) + return -1; + else + { + int_id = this->search_structure_[index].int_id_; + return 0; + } +} + +// Associate <ext_id> with <int_id>. If <ext_id> is already in the +// map then the <Map_Entry> is not changed. Returns 0 if a new +// entry is bound successfully, returns 1 if an attempt is made to +// bind an existing entry, and returns -1 if failures occur. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::bind_i (const EXT_ID &ext_id, + const INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::bind_i"); + + int first_free = -1; + int index = this->shared_find (ext_id, first_free); + + if (index >= 0) + // It was already bound, so return 1. + return 1; + + else + // We didn't find it, so let's bind it! + return this->shared_bind (ext_id, int_id, first_free); +} + +// Associate <ext_id> with <int_id>. If <ext_id> is not in the +// map then behaves just like <bind>. Otherwise, store the old +// values of <ext_id> and <int_id> into the "out" parameters and +// rebind the new parameters. This is very useful if you need to +// have an atomic way of updating <Map_Entries> and you also need +// full control over memory allocation. Returns 0 if a new entry is +// bound successfully, returns 1 if an existing entry was rebound, +// and returns -1 if failures occur. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::rebind_i (const EXT_ID &ext_id, + const INT_ID &int_id, + EXT_ID &old_ext_id, + INT_ID &old_int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::rebind_i"); + + int first_free = -1; + int index = this->shared_find (ext_id, first_free); + + if (index >= 0) + { + // We found it, so make copies of the old entries and rebind + // current entries. + + ACE_Map_Entry<EXT_ID, INT_ID> &ss = this->search_structure_[index]; + + old_ext_id = ss.ext_id_; + old_int_id = ss.int_id_; + ss.ext_id_ = ext_id; + ss.int_id_ = int_id; + this->allocator_->sync ((void *) &this->search_structure_[index], sizeof ss); + return 1; + } + else + // We didn't find it, so let's bind it! + return this->shared_bind (ext_id, int_id, first_free); +} + +// Find the INT_ID corresponding to the EXT_ID. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find_i (const EXT_ID &ext_id, + INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find_i"); + + int index = this->shared_find (ext_id); + + if (index == -1) + // Didn't find it. + return -1; + else + { + // Found it, so assign a copy. + int_id = this->search_structure_[index].int_id_; + return 0; + } +} + +// Unbind (remove) the EXT_ID from the map. Keeps track of where +// the EXT_ID was found so that this->unbind (EXT_ID, INT_ID) +// can return it to the caller. + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::shared_unbind (const EXT_ID &ext_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::shared_unbind"); + for (size_t i = 0; i < this->cur_size_; i++) + { + ACE_Map_Entry<EXT_ID, INT_ID> &ss = this->search_structure_[i]; + + if (ss.is_free_ == 0 && ss.ext_id_ == ext_id) + { + size_t index = i; + + // Mark this entry as being free. + ss.is_free_ = 1; + + this->allocator_->sync ((void *) &ss.is_free_, + sizeof ss.is_free_); + + // If we just unbound the highest active entry, then we need + // to figure out where the next highest active entry is. + + if (i + 1 == this->cur_size_) + { + while (i > 0 && this->search_structure_[--i].is_free_) + continue; + + if (i == 0 && this->search_structure_[i].is_free_) + this->cur_size_ = 0; + else + this->cur_size_ = i + 1; + this->allocator_->sync ((void *) &this->cur_size_, + sizeof this->cur_size_); + } + return index; + } + } + errno = ENOENT; + return -1; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind (const EXT_ID &ext_id, + INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind"); + ACE_Write_Guard<LOCK> m (this->lock_); + + return this->unbind_i (ext_id, int_id); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::bind (const EXT_ID &ext_id, + const INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::bind"); + ACE_Write_Guard<LOCK> m (this->lock_); + + return this->bind_i (ext_id, int_id); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::rebind (const EXT_ID &ext_id, + const INT_ID &int_id, + EXT_ID &old_ext_id, + INT_ID &old_int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::rebind"); + ACE_Write_Guard<LOCK> m (this->lock_); + + return this->rebind_i (ext_id, int_id, old_ext_id, old_int_id); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find (const EXT_ID &ext_id, + INT_ID &int_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::find"); + ACE_Read_Guard<LOCK> m (this->lock_); + + return this->find_i (ext_id, int_id); +} + +// Unbind (remove) the EXT_ID from the map. Don't return the INT_ID +// to the caller (this is useful for collections where the INT_IDs are +// *not* dynamically allocated...) + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind_i (const EXT_ID &ext_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind_i"); + return this->shared_unbind (ext_id) == -1 ? -1 : 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind (const EXT_ID &ext_id) +{ + ACE_TRACE ("ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::unbind"); + ACE_Write_Guard<LOCK> m (this->lock_); + return this->unbind_i (ext_id) == -1 ? -1 : 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::current_size (void) +{ + ACE_TRACE ("ACE_Map_Manager::current_size"); + ACE_Write_Guard<LOCK> m (this->lock_); + return this->cur_size_; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Manager<EXT_ID, INT_ID, LOCK>::total_size (void) +{ + ACE_TRACE ("ACE_Map_Manager::total_size"); + ACE_Write_Guard<LOCK> m (this->lock_); + return this->max_size_; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Map_Iterator) + +template <class EXT_ID, class INT_ID, class LOCK> void +ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "next_ = %d", this->next_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class EXT_ID, class INT_ID, class LOCK> +ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::ACE_Map_Iterator (ACE_Map_Manager<EXT_ID, INT_ID, LOCK> &mm) + : map_man_ (mm), + next_ (-1) +{ + ACE_TRACE ("ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::ACE_Map_Iterator"); + this->advance (); +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::next (ACE_Map_Entry<EXT_ID, INT_ID> *&mm) +{ + ACE_TRACE ("ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::next"); + ACE_Read_Guard<LOCK> m (this->map_man_.lock_); + + // Note that this->next_ is never negative at this point... + if (size_t (this->next_) < this->map_man_.cur_size_) + { + mm = &this->map_man_.search_structure_[this->next_]; + return 1; + } + else + return 0; +} + +template <class EXT_ID, class INT_ID, class LOCK> int +ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::advance (void) +{ + ACE_TRACE ("ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>::advance"); + ACE_Read_Guard<LOCK> m (this->map_man_.lock_); + + for (++this->next_; + size_t (this->next_) < this->map_man_.cur_size_ + && this->map_man_.search_structure_[this->next_].is_free_; + this->next_++) + continue; + return this->next_; +} + +#endif /* ACE_MAP_MANAGER_C */ diff --git a/ace/Map_Manager.h b/ace/Map_Manager.h new file mode 100644 index 00000000000..74f142ffcef --- /dev/null +++ b/ace/Map_Manager.h @@ -0,0 +1,262 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Map_Manager.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_MAP_MANAGER_H) +#define ACE_MAP_MANAGER_H + +#include "ace/ACE.h" + +// Forward declaration. +class ACE_Allocator; + +template <class EXT_ID, class INT_ID> +struct ACE_Map_Entry + // = TITLE + // An entry in the Map. +{ + EXT_ID ext_id_; + // Key used to look up an entry. + + INT_ID int_id_; + // The contents of the entry itself. + + int is_free_; + // Keeps track whether entry is free or not. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +// Forward decl. +template <class EXT_ID, class INT_ID, class LOCK> +class ACE_Map_Iterator; + +template <class EXT_ID, class INT_ID, class LOCK> +class ACE_Map_Manager + // = TITLE + // Define a map abstraction (useful for managing connections and + // sessions). + // + // = DESCRIPTION + // This implementation of a map uses an array. It should + // be enhanced to use a hash table... + // This class uses an ACE_Allocator to allocate memory + // The user can make this a persistant class by providing an + // ACE_Allocator with a persistable memory pool +{ +friend class ACE_Map_Iterator<EXT_ID, INT_ID, LOCK>; +public: + enum {DEFAULT_SIZE = ACE_DEFAULT_MAP_SIZE}; + + // = Initialization and termination methods. + ACE_Map_Manager (ACE_Allocator *allocator = 0); + // Initialize a <Map_Manager> with the <DEFAULT_SIZE>. + + ACE_Map_Manager (size_t size, ACE_Allocator *allocator = 0); + // Initialize a <Map_Manager> with <size> entries. + + int open (size_t length = DEFAULT_SIZE, + ACE_Allocator *allocator = 0); + // Initialize a <Map_Manager> with size <length>. + + int close (void); + // Close down a <Map_Manager> and release dynamically allocated + // resources. + + ~ACE_Map_Manager (void); + // Close down a <Map_Manager> and release dynamically allocated + // resources. + + int trybind (const EXT_ID &ext_id, INT_ID &int_id); + // Associate <ext_id> with <int_id> if and only if <ext_id> is not + // in the map. If <ext_id> is already in the map then the <int_id> + // parameter is overwritten with the existing value in the map + // Returns 0 if a new entry is bound successfully, returns 1 if an + // attempt is made to bind an existing entry, and returns -1 if + // failures occur. + + int bind (const EXT_ID &ext_id, const INT_ID &int_id); + // Associate <ext_id> with <int_id>. If <ext_id> is already in the + // map then the <Map_Entry> is not changed. Returns 0 if a new + // entry is bound successfully, returns 1 if an attempt is made to + // bind an existing entry, and returns -1 if failures occur. + + int rebind (const EXT_ID &ext_id, const INT_ID &int_id, + EXT_ID &old_ext_id, INT_ID &old_int_id); + // Associate <ext_id> with <int_id>. If <ext_id> is not in the + // map then behaves just like <bind>. Otherwise, store the old + // values of <ext_id> and <int_id> into the "out" parameters and + // rebind the new parameters. This is very useful if you need to + // have an atomic way of updating <Map_Entries> and you also need + // full control over memory allocation. Returns 0 if a new entry is + // bound successfully, returns 1 if an existing entry was rebound, + // and returns -1 if failures occur. + + int find (const EXT_ID &ext_id, INT_ID &int_id); + // Locate <ext_id> and pass out parameter via <int_id>. If found, + // return 0, returns -1 if failure occurs. + + int find (const EXT_ID &ext_id); + // Returns 0 if the <ext_id> is in the mapping, otherwise -1. + + int unbind (const EXT_ID &ext_id, INT_ID &int_id); + // Break any association of <ext_id>. Returns the value of <int_id> in + // case the caller needs to deallocate memory. + + int unbind (const EXT_ID &ext_id); + // Unbind (remove) the <ext_id> from the map. Don't return the <int_id> + // to the caller (this is useful for collections where the <int_id>s + // are *not* dynamically allocated...) + + int current_size (void); + // Return the current size of the map. + + int total_size (void); + // Return the total size of the map. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + + ACE_Map_Entry<EXT_ID, INT_ID> *search_structure_; + // Implementation of the Map (should use hashing instead of + // array...). + + // = The following methods do the actual work and assume that + // the locks are held by the private methods. + + int bind_i (const EXT_ID &ext_id, const INT_ID &int_id); + // Performs the binding of <ext_id> to <int_id>. Must be + // called with locks held. + + int rebind_i (const EXT_ID &ext_id, const INT_ID &int_id, + EXT_ID &old_ext_id, INT_ID &old_int_id); + // Performs a rebinding of <ext_it> to <int_id>. Must be called + // with locks held. + + int find_i (const EXT_ID &ext_id, INT_ID &int_id); + // Performs a find of <int_id> using <ext_id> as the key. Must be + // called with locks held. + + int find_i (const EXT_ID &ext_id); + // Performs a find using <ext_id> as the key. Must be called with + // locks held. + + int unbind_i (const EXT_ID &ext_id, INT_ID &int_id); + // Performs an unbind of <int_id> using <ext_id> as the key. Must + // be called with locks held. + + int unbind_i (const EXT_ID &ext_id); + // Performs an unbind using <ext_id> as the key. Must be called + // with locks held. + + int trybind_i (const EXT_ID &ext_id, INT_ID &int_id); + // Performs a conditional bind of <int_id> using <ext_id> as the + // key. Must be called with locks held. + + int resize_i (size_t size); + // Resize the map. Must be called with locks held. + + int close_i (void); + // Close down a <Map_Manager>. Must be called with + // locks held. + + ACE_Allocator *allocator_; + // Pointer to a memory allocator. + + LOCK lock_; + // Synchronization variable for the MT_SAFE ACE_Map_Manager. + +private: + + int shared_find (const EXT_ID &ext_id, int &first_free); + // Locate an entry, keeping track of the first free slot. Must be + // called with locks held. + + int shared_find (const EXT_ID &ext_id); + // Locate an entry. Must be called with locks held. + + int shared_bind (const EXT_ID &ext_id, const INT_ID &int_id, int first_free); + // Bind an entry. Must be called with locks held. + + int shared_unbind (const EXT_ID &ext_id); + // Unbind (remove) the <ext_id> from the map. Keeps track of where + // the <ext_id> was found so that this->unbind (<ext_id>, <int_id>) + // can return it to the caller. Must be called with locks held. + + size_t max_size_; + // Total number of elements in this->search_structure_. + + size_t cur_size_; + // Index of highest active elementin this->search_structure_. +}; + +template <class EXT_ID, class INT_ID, class LOCK> +class ACE_Map_Iterator + // = TITLE + // Iterator for the ACE_Map_Manager. + // + // = DESCRIPTION + // Allows deletions while iteration is occurring. +{ +public: + // = Initialization method. + ACE_Map_Iterator (ACE_Map_Manager <EXT_ID, INT_ID, LOCK> &mm); + + // = Iteration methods. + + int next (ACE_Map_Entry<EXT_ID, INT_ID> *&next_entry); + // Pass back the <entry> that hasn't been seen in the Set. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Map_Manager <EXT_ID, INT_ID, LOCK> &map_man_; + // Map we are iterating over. + + ssize_t next_; + // Keeps track of how far we've advanced... +}; + +#if defined (__ACE_INLINE__) +#include "ace/Map_Manager.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Map_Manager.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Map_Manager.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_MAP_MANAGER_H */ diff --git a/ace/Map_Manager.i b/ace/Map_Manager.i new file mode 100644 index 00000000000..7e1703cd066 --- /dev/null +++ b/ace/Map_Manager.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Map_Manager.i diff --git a/ace/Mem_Map.cpp b/ace/Mem_Map.cpp new file mode 100644 index 00000000000..9f392f85f15 --- /dev/null +++ b/ace/Mem_Map.cpp @@ -0,0 +1,218 @@ +// Mem_Map.cpp +// $Id$ + +// Defines the member functions for the memory mapping facility. + +#define ACE_BUILD_DLL +#include "ace/Mem_Map.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Mem_Map.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Mem_Map) + +void +ACE_Mem_Map::dump (void) const +{ + ACE_TRACE ("ACE_Mem_Map::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "base_addr_ = %x", this->base_addr_)); + ACE_DEBUG ((LM_DEBUG, "\nfilename_ = %s", this->filename_)); + ACE_DEBUG ((LM_DEBUG, "\nlength_ = %d", this->length_)); + ACE_DEBUG ((LM_DEBUG, "\nhandle_ = %d", this->handle_)); + ACE_DEBUG ((LM_DEBUG, "\nfile_mapping_ = %d", this->file_mapping_)); + ACE_DEBUG ((LM_DEBUG, "\nclose_handle_ = %d", this->close_handle_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_Mem_Map::close (void) +{ + ACE_TRACE ("ACE_Mem_Map::close"); + + this->unmap (); + + if (this->file_mapping_ != this->handle_) + ACE_OS::close (this->file_mapping_); + + if (this->close_handle_) + return ACE_OS::close (this->handle_); + + return 0; +} + +ACE_Mem_Map::~ACE_Mem_Map (void) +{ + ACE_TRACE ("ACE_Mem_Map::~ACE_Mem_Map"); + + this->close (); +} + +// This function does the dirty work of actually calling ACE_OS::mmap +// to map the file into memory. + +int +ACE_Mem_Map::map_it (ACE_HANDLE handle, + int len_request, + int prot, + int share, + void *addr, + off_t pos) +{ + ACE_TRACE ("ACE_Mem_Map::map_it"); + this->base_addr_ = addr; + this->handle_ = handle; + + long file_len = ACE_OS::filesize (this->handle_); + + if (file_len == -1) + return -1; + + if (this->length_ < size_t (file_len)) + { + // If the length of the mapped region is less than the length of + // the file then we force a complete new remapping by setting + // the descriptor to ACE_INVALID_HANDLE (closing down the + // descriptor if necessary). + if (this->file_mapping_ != this->handle_) + ACE_OS::close (this->file_mapping_); + this->file_mapping_ = ACE_INVALID_HANDLE; + } + + // At this point we know <file_len> is not negative... + this->length_ = size_t (file_len); + + if (len_request == -1) + len_request = 0; + + if ((this->length_ == 0 && len_request > 0) + || this->length_ < size_t (len_request)) + { + this->length_ = len_request; + + // Extend the backing store. + if (ACE_OS::lseek (this->handle_, + len_request > 0 ? len_request - 1 : 0, + SEEK_SET) == -1 + || ACE_OS::write (this->handle_, "", 1) == -1 + || ACE_OS::lseek (this->handle_, 0, SEEK_SET) == -1) + return -1; + } + + this->base_addr_ = ACE_OS::mmap (this->base_addr_, + this->length_, + prot, + share, + this->handle_, + off_t (ACE::round_to_pagesize (pos)), + &this->file_mapping_); + + return this->base_addr_ == MAP_FAILED ? -1 : 0; +} + +int +ACE_Mem_Map::open (LPCTSTR file_name, + int flags, + int mode) +{ + ACE_TRACE ("ACE_Mem_Map::open"); + + ACE_OS::strncpy (this->filename_, file_name, MAXPATHLEN); + + this->handle_ = ACE_OS::open (file_name, flags, mode); + + if (this->handle_ == ACE_INVALID_HANDLE) + return -1; + else + { + this->close_handle_ = 1; + return 0; + } +} + +int +ACE_Mem_Map::map (const char file_name[], + int len, + int flags, + int mode, + int prot, + int share, + void *addr, + off_t pos) +{ + ACE_TRACE ("ACE_Mem_Map::map"); + this->length_ = 0; + + if (this->open (file_name, flags, mode) == -1) + return -1; + else + return this->map_it (this->handle (), len, prot, share, addr, pos); +} + +ACE_Mem_Map::ACE_Mem_Map (void) + : length_ (0), + base_addr_ (0), + handle_ (ACE_INVALID_HANDLE), + file_mapping_ (ACE_INVALID_HANDLE), + close_handle_ (0) +{ + ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map"); + ACE_OS::memset (this->filename_, 0, sizeof this->filename_); +} + +// Map a file specified by FILE_NAME. + +ACE_Mem_Map::ACE_Mem_Map (const char file_name[], + int len, + int flags, + int mode, + int prot, + int share, + void *addr, + off_t pos) + : base_addr_ (0), + close_handle_ (0), + file_mapping_ (ACE_INVALID_HANDLE) +{ + ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map"); + if (this->map (file_name, len, flags, mode, prot, share, addr, pos) < 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Mem_Map::ACE_Mem_Map")); +} + +// Map a file from an open file descriptor HANDLE. This function will +// lookup the length of the file if it is not given. + +ACE_Mem_Map::ACE_Mem_Map (ACE_HANDLE handle, + int len, + int prot, + int share, + void *addr, + off_t pos) + : close_handle_ (0), + file_mapping_ (ACE_INVALID_HANDLE) +{ + ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map"); + + ACE_OS::memset (this->filename_, 0, sizeof this->filename_); + + if (this->map (handle, len, prot, share, addr, pos) < 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Mem_Map::ACE_Mem_Map")); +} + +// Close down and remove the file from the file system. + +int +ACE_Mem_Map::remove (void) +{ + ACE_TRACE ("ACE_Mem_Map::remove"); + + ACE_OS::ftruncate (this->handle_, 0); + this->close (); + + if (this->filename_[0] != '\0') + return ACE_OS::unlink (this->filename_); + else + return 0; +} diff --git a/ace/Mem_Map.h b/ace/Mem_Map.h new file mode 100644 index 00000000000..ee439b1e5a5 --- /dev/null +++ b/ace/Mem_Map.h @@ -0,0 +1,179 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Mem_Map.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_MEM_MAP_H) +#define ACE_MEM_MAP_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Mem_Map + // = TITLE + // C++ interface to the mmap(2) UNIX system call. +{ +public: + // = Initialization and termination methods. + + ACE_Mem_Map (void); + // Default constructor. + + ACE_Mem_Map (ACE_HANDLE handle, + int length = -1, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + void *addr = 0, + off_t pos = 0); + // Map a file from an open file descriptor <handle>. This function + // will lookup the length of the file if it is not given. + + ACE_Mem_Map (LPCTSTR filename, + int len = -1, + int flags = O_RDWR | O_CREAT, + int mode = ACE_DEFAULT_PERMS, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + void *addr = 0, + off_t pos = 0); + // Map a file specified by <file_name>. + + int map (ACE_HANDLE handle, + int length = -1, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + void *addr = 0, + off_t pos = 0); + // Map a file from an open file descriptor <handle>. This function + // will lookup the length of the file if it is not given. + + int map (int length = -1, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + void *addr = 0, + off_t pos = 0); + // Remap the file associated with <handle_>. + + int map (LPCTSTR filename, + int len = -1, + int flags = O_RDWR | O_CREAT, + int mode = ACE_DEFAULT_PERMS, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + void *addr = 0, + off_t pos = 0); + // Map a file specified by <filename>. + + ~ACE_Mem_Map (void); + // Destructor. + + int open (LPCTSTR filename, + int flags = O_RDWR | O_CREAT, + int mode = ACE_DEFAULT_PERMS); + // Open the file without mapping it. + + int close (void); + // Close down the <handle_> if necessary. + + int operator () (void *&addr); + // This operator passes back the starting address of the mapped + // file. + + void *addr (void) const; + // Return the base address. + + size_t size (void) const; + // This function returns the number of bytes currently mapped in the + // file. + + int unmap (int len = -1); + // Unmap the region starting at <base_addr_>. + + int unmap (void *addr, int len); + // Unmap the region starting at <addr_>. + + int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <base_addr_>. If <len> == -1 then sync the whole + // region. + + int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <addr_>. + + int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <base_addr_> up to <len> bytes. If <len> == -1 then + // change protection of all pages in the mapped region. + + int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + int remove (void); + // Close down and remove the file from the file system. + + int advise (int behavior, int len = -1); + // Hook into the underlying VM system. + + ACE_HANDLE handle (void) const; + // Return the underlying <handle_>. + + const TCHAR *filename (void) const; + // Return the name of file that is mapped (if any). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + void *base_addr_; + // Base address of the memory-mapped file. + + TCHAR filename_[MAXPATHLEN + 1]; + // Name of the file that is mapped. + + size_t length_; + // Length of the mapping. + + ACE_HANDLE handle_; + // HANDLE for the open file. + + ACE_HANDLE file_mapping_; + // HANDLE for the open mapping. + + int close_handle_; + // Keeps track of whether we need to close the handle. This is set + // if we opened the file. + + int map_it (ACE_HANDLE handle, + int len = -1, + int prot = PROT_RDWR, + int share = MAP_SHARED, + void *addr = 0, + off_t pos = 0); + // This method does the dirty work of actually calling ::mmap to map + // the file into memory. + + ACE_Mem_Map (const ACE_Mem_Map &) {} + void operator = (const ACE_Mem_Map &) {} +}; + +#if defined (__ACE_INLINE__) +#include "ace/Mem_Map.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_MEM_MAP_H */ diff --git a/ace/Mem_Map.i b/ace/Mem_Map.i new file mode 100644 index 00000000000..ecba43e127d --- /dev/null +++ b/ace/Mem_Map.i @@ -0,0 +1,166 @@ +/* -*- C++ -*- */ +// $Id$ + +// Mem_Map.i + +#include "ace/Log_Msg.h" + +ACE_INLINE ACE_HANDLE +ACE_Mem_Map::handle (void) const +{ + ACE_TRACE ("ACE_Mem_Map::handle"); + return this->handle_; +} + +// Return the name of file that is mapped (if any). + +ACE_INLINE const TCHAR * +ACE_Mem_Map::filename (void) const +{ + return this->filename_; +} + +ACE_INLINE int +ACE_Mem_Map::map (ACE_HANDLE handle, + int len, + int prot, + int share, + void *addr, + off_t pos) +{ + ACE_TRACE ("ACE_Mem_Map::map"); + return this->map_it (handle, len, prot, share, addr, pos); +} + +// Remap the file associated with <this->handle_>. + +ACE_INLINE int +ACE_Mem_Map::map (int len, + int prot, + int share, + void *addr, + off_t pos) +{ + ACE_TRACE ("ACE_Mem_Map::map"); + return this->map_it (this->handle (), len, prot, + share, addr, pos); +} + +// This operator passes back the starting address of the mapped file. + +ACE_INLINE int +ACE_Mem_Map::operator () (void *&addr) +{ + ACE_TRACE ("ACE_Mem_Map::operator"); + + if (this->base_addr_ == MAP_FAILED) + return -1; + else + { + addr = this->base_addr_; + return 0; + } +} + +// Return the base address. + +ACE_INLINE void * +ACE_Mem_Map::addr (void) const +{ + ACE_TRACE ("ACE_Mem_Map::addr"); + + return this->base_addr_; +} + +// This function returns the number of bytes currently mapped in the +// file. + +ACE_INLINE size_t +ACE_Mem_Map::size (void) const +{ + ACE_TRACE ("ACE_Mem_Map::size"); + return this->length_; +} + +// Unmap the region starting at <this->base_addr_>. + +ACE_INLINE int +ACE_Mem_Map::unmap (int len) +{ + ACE_TRACE ("ACE_Mem_Map::unmap"); + if (this->file_mapping_ != this->handle_) + ACE_OS::close (this->file_mapping_); + + this->file_mapping_ = ACE_INVALID_HANDLE; + + return ACE_OS::munmap (this->base_addr_, len < 0 ? this->length_ : len); +} + +// Unmap the region starting at <addr_>. + +ACE_INLINE int +ACE_Mem_Map::unmap (void *addr, int len) +{ + ACE_TRACE ("ACE_Mem_Map::unmap"); + if (this->file_mapping_ != this->handle_) + ACE_OS::close (this->file_mapping_); + + this->file_mapping_ = ACE_INVALID_HANDLE; + + return ACE_OS::munmap (addr, len < 0 ? this->length_ : len); +} + +// Sync <len> bytes of the memory region to the backing store starting +// at <this->base_addr_>. If <len> == -1 then sync the whole mapped +// region. + +ACE_INLINE int +ACE_Mem_Map::sync (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_Mem_Map::sync"); + return ACE_OS::msync (this->base_addr_, len < 0 ? this->length_ : len, flags); +} + +// Sync <len> bytes of the memory region to the backing store starting +// at <addr_>. + +ACE_INLINE int +ACE_Mem_Map::sync (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_Mem_Map::sync"); + return ACE_OS::msync (addr, len, flags); +} + +// Change the protection of the pages of the mapped region to <prot> +// starting at <this->base_addr_> up to <len> bytes. If <len> == -1 +// then change protection of all pages in the mapped region. + +ACE_INLINE int +ACE_Mem_Map::protect (ssize_t len, int prot) +{ + ACE_TRACE ("ACE_Mem_Map::protect"); + if (len < 0) + len = this->length_; + return ACE_OS::mprotect (this->base_addr_, len, prot); +} + +// Change the protection of the pages of the mapped region to <prot> +// starting at <addr> up to <len> bytes. + +ACE_INLINE int +ACE_Mem_Map::protect (void *addr, size_t len, int prot) +{ + ACE_TRACE ("ACE_Mem_Map::protect"); + return ACE_OS::mprotect (addr, len, prot); +} + +// Hook into the underlying VM system. + +ACE_INLINE int +ACE_Mem_Map::advise (int behavior, int len) +{ + ACE_TRACE ("ACE_Mem_Map::advise"); + if (len < 0) + len = this->length_; + return ACE_OS::madvise ((caddr_t) this->base_addr_, len, behavior); +} diff --git a/ace/Memory_Pool.cpp b/ace/Memory_Pool.cpp new file mode 100644 index 00000000000..2ec2b76c6a9 --- /dev/null +++ b/ace/Memory_Pool.cpp @@ -0,0 +1,587 @@ + +// $Id$ + +// Memory_Pool.cpp +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Memory_Pool.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Memory_Pool.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Local_Memory_Pool) + +void +ACE_Local_Memory_Pool::dump (void) const +{ + ACE_TRACE ("ACE_Local_Memory_Pool::dump"); +} + +ACE_Local_Memory_Pool::ACE_Local_Memory_Pool (const char *) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::ACE_Local_Memory_Pool"); +} + +void * +ACE_Local_Memory_Pool::acquire (size_t nbytes, + size_t &rounded_bytes) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::acquire"); + rounded_bytes = this->round_up (nbytes); + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n", nbytes, rounded_bytes)); + + void *cp = (void *) new char[rounded_bytes]; + + if (cp == 0) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %u\n", cp), 0); + else + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %d\n", nbytes, rounded_bytes, cp)); + return cp; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_MMAP_Memory_Pool) + +void +ACE_MMAP_Memory_Pool::dump (void) const +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::dump"); +} + +int +ACE_MMAP_Memory_Pool::release (void) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::release"); + this->mmap_.remove (); + return 0; +} + +int +ACE_MMAP_Memory_Pool::sync (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::sync"); + + if (len < 0) + len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END); + + return this->mmap_.sync (len, flags); +} + +// Sync <len> bytes of the memory region to the backing store starting +// at <addr_>. + +int +ACE_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::sync"); + return ACE_OS::msync (addr, len, flags); +} + +// Change the protection of the pages of the mapped region to <prot> +// starting at <this->base_addr_> up to <len> bytes. If <len> == -1 +// then change protection of all pages in the mapped region. + +int +ACE_MMAP_Memory_Pool::protect (ssize_t len, int prot) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::protect"); + + if (len < 0) + len = ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END); + + return this->mmap_.protect (len, prot); +} + +// Change the protection of the pages of the mapped region to <prot> +// starting at <addr> up to <len> bytes. + +int +ACE_MMAP_Memory_Pool::protect (void *addr, size_t len, int prot) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::protect"); + return ACE_OS::mprotect (addr, len, prot); +} + +ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool (const char *pool_name, + int use_fixed_addr, + int write_each_page, + char *base_addr) + : base_addr_ (use_fixed_addr ? base_addr : 0), + flags_ (MAP_SHARED | (use_fixed_addr ? MAP_FIXED : 0)), + write_each_page_ (write_each_page) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::ACE_MMAP_Memory_Pool"); + + if (pool_name == 0) + // Only create a new unique filename for the backing store file + // if the user didn't supply one... + pool_name = ACE_DEFAULT_BACKING_STORE; // from "ace/OS.h" + + ACE_OS::strncpy (this->backing_store_, pool_name, + sizeof this->backing_store_); + + if (this->signal_handler_.register_handler (SIGSEGV, this) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", this->backing_store_)); +} + +// Compute the new file_offset of the backing store and commit the +// memory. + +int +ACE_MMAP_Memory_Pool::commit_backing_store (size_t rounded_bytes, + off_t &file_offset) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::commit_backing_store"); + + size_t seek_len; + + if (this->write_each_page_) + // Write to the end of every block to ensure that we have enough + // space in the backing store. + seek_len = this->round_up (1); // round_up(1) is one page. + else + // We're willing to risk it all in the name of efficiency... + seek_len = rounded_bytes; + + // The following loop will execute multiple times (if + // this->write_each_page == 1) or just once (if + // this->write_each_page == 0). + + for (size_t cur_block = 0; + cur_block < rounded_bytes; + cur_block += seek_len) + { + file_offset = ACE_OS::lseek (this->mmap_.handle () , seek_len - 1, SEEK_END); + + if (file_offset == -1 || ACE_OS::write (this->mmap_.handle (), "", 1) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", this->backing_store_), -1); + } + + // Increment by one to put us at the beginning of the next chunk... + file_offset++; + return 0; +} + +// Memory map the file up to <file_offset> bytes. + +int +ACE_MMAP_Memory_Pool::map_file (off_t file_offset) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::map_file"); + + // Unmap the existing mapping. + this->mmap_.unmap (); + + // Remap the file. + if (this->mmap_.map (file_offset, PROT_RDWR, + this->flags_, this->base_addr_, 0) == -1 + || this->base_addr_ != 0 && this->mmap_.addr () != this->base_addr_) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) base_addr = %u, addr = %u, file_offset = %u, %p\n", + this->mmap_.addr (), this->base_addr_, + file_offset, this->backing_store_), -1); + + return 0; +} + +// Ask operating system for more shared memory, increasing the mapping +// accordingly. Note that this routine assumes that the appropriate +// locks are held when it is called. + +void * +ACE_MMAP_Memory_Pool::acquire (size_t nbytes, + size_t &rounded_bytes) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::acquire"); + rounded_bytes = this->round_up (nbytes); + + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes = + // %d, rounded_bytes = %d\n", nbytes, rounded_bytes)); + + off_t file_offset; + + if (this->commit_backing_store (rounded_bytes, file_offset) == -1) + return 0; + + if (this->map_file (file_offset) == -1) + return 0; + + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d, + // rounded_bytes = %d, file_offset = %d\n", nbytes, rounded_bytes, + // file_offset)); + + return (void *) ((char *) this->mmap_.addr () + (this->mmap_.size () - rounded_bytes)); +} + +// Ask system for initial chunk of shared memory. + +void * +ACE_MMAP_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::init_acquire"); + + first_time = 0; + + if (this->mmap_.open (this->backing_store_, + O_RDWR | O_CREAT | O_TRUNC | O_EXCL, + ACE_DEFAULT_PERMS) != -1) + { + // First time in, so need to acquire memory. + first_time = 1; + return this->acquire (nbytes, rounded_bytes); + } + else if (errno == EEXIST) + { + // Reopen file *without* using O_EXCL... + if (this->mmap_.map (this->backing_store_, + -1, + O_RDWR, + ACE_DEFAULT_PERMS, + PROT_RDWR, + this->flags_, + this->base_addr_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), 0); + + return this->mmap_.addr (); + } + else + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), 0); +} + +int +ACE_MMAP_Memory_Pool::remap (void *addr) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::remap"); + ACE_DEBUG ((LM_DEBUG, "Remapping with fault address at: %X\n", addr)); + off_t current_file_offset = ACE_OS::filesize (this->mmap_.handle ()); + // ACE_OS::lseek (this->mmap_.handle (), 0, SEEK_END); + + if (addr != 0 + && !(addr < (void *) ((char *) this->mmap_.addr () + current_file_offset) + && addr >= this->mmap_.addr ())) + return -1; + + // Extend the mapping to cover the size of the backing store. + return this->map_file (current_file_offset); +} + +// Handle SIGSEGV and SIGBUS signals to remap memory properly. When a +// process reads or writes to non-mapped memory a signal (SIGBUS or +// SIGSEGV) will be triggered. At that point, the ACE_Sig_Handler +// (which is part of the ACE_Reactor) will catch the signal and +// dispatch the handle_signal() method defined here. If the SIGSEGV +// signal occurred due to the fact that the mapping wasn't uptodate +// with respect to the backing store, the handler method below will +// update the mapping accordingly. When the signal handler returns, +// the instruction should be restarted and the operation should work. + +int +ACE_MMAP_Memory_Pool::handle_signal (int signum, siginfo_t *siginfo, ucontext_t *) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::handle_signal"); + + if (signum != SIGSEGV) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) ignoring signal %S\n", + signum), -1); + else + ; // ACE_DEBUG ((LM_DEBUG, "(%P|%t) received %S\n", signum)); + + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) new mapping address = %u\n", (char *) this->base_addr_ + current_file_offset)); + +#if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) + // Make sure that the pointer causing the problem is within the + // range of the backing store. + + if (siginfo != 0) + { + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) si_signo = %d, si_code = %d, addr = %u\n", siginfo->si_signo, siginfo->si_code, siginfo->si_addr)); + if (this->remap ((void *) siginfo->si_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n", + siginfo->si_addr), -1); + return 0; + } +#endif /* ACE_HAS_SIGINFO_T && !defined ACE_LACKS_SI_ADDR */ + // This is total desperation since we don't know what the faulting + // address is in this case! + this->remap (0); + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Lite_MMAP_Memory_Pool) + +ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool (const char *pool_name, + int use_fixed_addr, + int write_each_page, + char *base_addr) + : ACE_MMAP_Memory_Pool (pool_name, use_fixed_addr, write_each_page, base_addr) +{ + ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::ACE_Lite_MMAP_Memory_Pool"); +} + +int +ACE_Lite_MMAP_Memory_Pool::sync (ssize_t len, int flags) +{ + ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync"); + return 0; +} + +int +ACE_Lite_MMAP_Memory_Pool::sync (void *addr, size_t len, int flags) +{ + ACE_TRACE ("ACE_Lite_MMAP_Memory_Pool::sync"); + return 0; +} + +#if !defined (ACE_LACKS_SBRK) +ACE_ALLOC_HOOK_DEFINE(ACE_Sbrk_Memory_Pool) + +// Ask system for more local memory via sbrk(2). + +void * +ACE_Sbrk_Memory_Pool::acquire (size_t nbytes, + size_t &rounded_bytes) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::acquire"); + rounded_bytes = this->round_up (nbytes); + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n", nbytes, rounded_bytes)); + void *cp = ACE_OS::sbrk (rounded_bytes); + + if (cp == MAP_FAILED) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) cp = %u\n", cp), 0); + else + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d, new break = %u\n", nbytes, rounded_bytes, cp)); + return cp; +} + +void +ACE_Sbrk_Memory_Pool::dump (void) const +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::dump"); +} + +ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool (const char *) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::ACE_Sbrk_Memory_Pool"); +} +#endif /* !ACE_LACKS_SBRK */ + +#if !defined (ACE_LACKS_SYSV_SHMEM) +ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_Pool) + +void +ACE_Shared_Memory_Pool::dump (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::dump"); +} + +int +ACE_Shared_Memory_Pool::in_use (off_t &offset, + int &counter) +{ + offset = 0; + SHM_TABLE *st = (SHM_TABLE *) ACE_DEFAULT_BASE_ADDR; + shmid_ds buf; + + for (counter = 0; + counter < ACE_DEFAULT_MAX_SEGMENTS + && st[counter].used == 1; + counter++) + { + if (ACE_OS::shmctl (st[counter].shmid, IPC_STAT, &buf) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "shmctl"), -1); + offset += buf.shm_segsz; + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) segment size = %d, offset = %d\n", buf.shm_segsz, offset)); + } + + return 0; +} + +int +ACE_Shared_Memory_Pool::commit_backing_store (size_t rounded_bytes, + off_t &offset) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::update"); + int counter; + SHM_TABLE *st = (SHM_TABLE *) ACE_DEFAULT_BASE_ADDR; + + if (this->in_use (offset, counter) == -1) + return -1; + + if (counter == ACE_DEFAULT_MAX_SEGMENTS) + ACE_ERROR_RETURN ((LM_ERROR, + "exceeded max number of segments = %d, base = %u, offset = %u\n", + counter, ACE_DEFAULT_BASE_ADDR, offset), -1); + else + { + int shmid = ACE_OS::shmget (st[counter].key, + rounded_bytes, + ACE_DEFAULT_PERMS | IPC_CREAT | IPC_EXCL); + if (shmid == -1) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "shmget"), 0); + + st[counter].shmid = shmid; + st[counter].used = 1; + + void *address = (void *) (ACE_DEFAULT_BASE_ADDR + offset); + void *shmem = ACE_OS::shmat (st[counter].shmid, (char *) address, 0); + + if (shmem != address) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, shmem = %u, address = %u\n", + "shmat", shmem, address), 0); + } + + return 0; +} + +// Handle SIGSEGV and SIGBUS signals to remap shared memory properly. + +int +ACE_Shared_Memory_Pool::handle_signal (int , siginfo_t *siginfo, ucontext_t *) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::handle_signal"); + // ACE_DEBUG ((LM_DEBUG, "signal %S occurred\n", signum)); + off_t offset; + +#if defined (ACE_HAS_SIGINFO_T) && !defined (ACE_LACKS_SI_ADDR) + // Make sure that the pointer causing the problem is within the + // range of the backing store. + + if (siginfo != 0) + { + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) si_signo = %d, si_code = %d, addr = %u\n", siginfo->si_signo, siginfo->si_code, siginfo->si_addr)); + int counter; + if (this->in_use (offset, counter) == -1) + ACE_ERROR ((LM_ERROR, "(%P|%t) %p\n", "in_use")); + else if (!(siginfo->si_code == SEGV_MAPERR + && siginfo->si_addr < (((char *) ACE_DEFAULT_BASE_ADDR) + offset) + && siginfo->si_addr >= ((char *) ACE_DEFAULT_BASE_ADDR))) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) address %u out of range\n", + siginfo->si_addr), -1); + } +#endif /* ACE_HAS_SIGINFO_T && !defined (ACE_LACKS_SI_ADDR) */ + this->commit_backing_store (this->round_up (ACE_DEFAULT_SEGMENT_SIZE), + offset); + return 0; +} + +ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool (const char *pool_name) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::ACE_Shared_Memory_Pool"); + + if (this->signal_handler_.register_handler (SIGSEGV, this) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Sig_Handler::register_handler")); +} + +// Ask system for more shared memory. + +void * +ACE_Shared_Memory_Pool::acquire (size_t nbytes, + size_t &rounded_bytes) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::acquire"); + + rounded_bytes = this->round_up (nbytes); + + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquiring more chunks, nbytes = %d, rounded_bytes = %d\n", nbytes, rounded_bytes)); + + off_t offset; + + if (this->commit_backing_store (rounded_bytes, offset) == -1) + return 0; + + SHM_TABLE *st = (SHM_TABLE *) ACE_DEFAULT_BASE_ADDR; + void *new_memory = ((char *) ACE_DEFAULT_BASE_ADDR) + offset; + + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) acquired more chunks, nbytes = %d, rounded_bytes = %d\n", nbytes, rounded_bytes)); + return new_memory; +} + +// Ask system for initial chunk of shared memory. + +void * +ACE_Shared_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::init_acquire"); + + int counter; + void *base_addr = (void *) ACE_DEFAULT_BASE_ADDR; + off_t shm_table_offset = ACE::round_to_pagesize (sizeof (SHM_TABLE)); + rounded_bytes = this->round_up (nbytes); + + // Acquire the semaphore to serialize initialization and prevent + // race conditions. + + int shmid = ACE_OS::shmget (ACE_DEFAULT_SHM_KEY, + rounded_bytes + shm_table_offset, + ACE_DEFAULT_PERMS | IPC_CREAT | IPC_EXCL); + if (shmid == -1) + { + if (errno != EEXIST) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "shmget"), 0); + + first_time = 0; + + shmid = ACE_OS::shmget (ACE_DEFAULT_SHM_KEY, 0, 0); + + if (shmid == -1) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "shmget"), 0); + + void *shmem = ACE_OS::shmat (shmid, (char *) base_addr, 0); + + if (shmem != base_addr) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, shmem = %u, base_addr = %u\n", + "shmat", shmem, base_addr), 0); + } + else + { + first_time = 1; + + void *shmem = ACE_OS::shmat (shmid, (char *) base_addr, 0); + + if (shmem != base_addr) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p, shmem = %u, base_addr = %u\n", + "shmat", shmem, base_addr), 0); + + SHM_TABLE *st = (SHM_TABLE *) base_addr; + + st[0].key = ACE_DEFAULT_SHM_KEY; + st[0].shmid = shmid; + st[0].used = 1; + + for (counter = 1; // Skip over the first entry... + counter < ACE_DEFAULT_MAX_SEGMENTS; + counter++) + { + st[counter].key = ACE_DEFAULT_SHM_KEY + counter; + st[counter].shmid = 0; + st[counter].used = 0; + } + } + + return (void *) (((char *) base_addr) + shm_table_offset); +} + +// Instruct the memory pool to release all of its resources. + +int +ACE_Shared_Memory_Pool::release (void) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::release"); + + int result = 0; + SHM_TABLE *st = (SHM_TABLE *) ACE_DEFAULT_BASE_ADDR; + + for (int counter = 0; + counter < ACE_DEFAULT_MAX_SEGMENTS && st[counter].used == 1; + counter++) + if (ACE_OS::shmctl (st[counter].shmid, IPC_RMID, NULL) == -1) + result = -1; + + return result; +} +#endif /* !ACE_LACKS_SYSV_SHMEM */ diff --git a/ace/Memory_Pool.h b/ace/Memory_Pool.h new file mode 100644 index 00000000000..de4c69126f8 --- /dev/null +++ b/ace/Memory_Pool.h @@ -0,0 +1,352 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE_Memory_Pool.h +// +// = AUTHOR +// Doug Schmidt and Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_MEMORY_POOL_H) +#define ACE_MEMORY_POOL_H + +#include "ace/ACE.h" +#include "ace/Event_Handler.h" +#include "ace/Signal.h" +#include "ace/Mem_Map.h" +#if !defined (ACE_WIN32) +#include "ace/SV_Semaphore_Complex.h" +#endif /* !ACE_WIN32 */ + +#if !defined (ACE_LACKS_SBRK) +class ACE_Export ACE_Sbrk_Memory_Pool + // = TITLE + // Make a memory pool that is based on <sbrk(2)>. +{ +public: + ACE_Sbrk_Memory_Pool (const char *pool_name = 0); + // Initialization constructor. + + // = Implementor operations. + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + // Ask system for initial chunk of local memory. + + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + // Acquire at least NBYTES from the memory pool. ROUNDED_BYTES is + // the actual number of bytes allocated. + + virtual int release (void); + // Instruct the memory pool to release all of its resources. + + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <this->base_addr_>. If <len> == -1 then sync the + // whole region. + + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <addr_>. + + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + virtual void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + virtual size_t round_up (size_t nbytes); + // Implement the algorithm for rounding up the request to an + // appropriate chunksize. +}; +#endif /* !ACE_LACKS_SBRK */ + +#if !defined (ACE_LACKS_SYSV_SHMEM) +class ACE_Export ACE_Shared_Memory_Pool : public ACE_Event_Handler + // = TITLE + // Make a memory pool that is based on System V shared memory + // (shmget(2) etc.). This implementation allows memory to be + // shared between processes. +{ +public: + ACE_Shared_Memory_Pool (const char *pool_name = ACE_ITOA (ACE_DEFAULT_SHM_KEY)); + // Initialization constructor. + + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + // Ask system for initial chunk of local memory. + + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + // Acquire at least NBYTES from the memory pool. ROUNDED_BYTES is + // the actual number of bytes allocated. Also acquires an internal + // semaphore that ensures proper serialization of Memory_Pool + // initialization across processes. + + virtual int release (void); + // Instruct the memory pool to release all of its resources. + + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync the memory region to the backing store starting at + // <this->base_addr_>. + + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync the memory region to the backing store starting at <addr_>. + + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + virtual void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + virtual size_t round_up (size_t nbytes); + // Implement the algorithm for rounding up the request to an + // appropriate chunksize. + + virtual int commit_backing_store (size_t rounded_bytes, + off_t &offset); + // Commits a new shared memory segment if necessary after an + // acquire() or a signal. <offset> is set to the new offset into + // the backing store. + + struct SHM_TABLE + { + key_t key; + int shmid; + int used; + }; + + virtual int in_use (off_t &offset, int &counter); + // Determine how much memory is currently in use. + + ACE_Sig_Handler signal_handler_; + // Handles SIGSEGV. + + virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); + // Handle SIGSEGV and SIGBUS signals to remap shared memory + // properly. + + ACE_SV_Semaphore_Complex init_finished_; + // Used to serialize initialization of the Memory_Pool and Malloc. +}; +#endif /* !ACE_LACKS_SYSV_SHMEM */ + +class ACE_Export ACE_Local_Memory_Pool + // = TITLE + // Make a memory pool that is based on C++ new/delete. This is + // useful for integrating existing components that use new/delete + // into the ACE Malloc scheme... +{ +public: + ACE_Local_Memory_Pool (const char *pool_name = 0); + // Initialization constructor. + + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + // Ask system for initial chunk of local memory. + + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + // Acquire at least NBYTES from the memory pool. ROUNDED_BYTES is + // the actual number of bytes allocated. + + virtual int release (void); + // Instruct the memory pool to release all of its resources. + + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <this->base_addr_>. If <len> == -1 then sync the + // whole region. + + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync <len> bytes of the memory region to the backing store + // starting at <addr_>. + + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + virtual void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + virtual size_t round_up (size_t nbytes); + + // Implement the algorithm for rounding up the request to an + // appropriate chunksize. +}; + +class ACE_Export ACE_MMAP_Memory_Pool : public ACE_Event_Handler + // = TITLE + // Make a memory pool that is based on <mmap(2)>. This + // implementation allows memory to be shared between processes. +{ +public: + // = Initialization and termination methods. + ACE_MMAP_Memory_Pool (const char *pool_name = 0, + int use_fixed_addr = 1, + int write_each_page = 1, + char *base_addr = ACE_DEFAULT_BASE_ADDR); + // Initialize the pool. + + virtual void *init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time); + // Ask system for initial chunk of shared memory. + + virtual void *acquire (size_t nbytes, + size_t &rounded_bytes); + // Acquire at least <nbytes> from the memory pool. <rounded_bytes> + // is the actual number of bytes allocated. Also acquires an + // internal semaphore that ensures proper serialization of + // <ACE_MMAP_Memory_Pool> initialization across processes. + + virtual int release (void); + // Instruct the memory pool to release all of its resources. + + virtual int sync (ssize_t len = -1, int flags = MS_SYNC); + // Sync the memory region to the backing store starting at + // <this->base_addr_>. + + virtual int sync (void *addr, size_t len, int flags = MS_SYNC); + // Sync the memory region to the backing store starting at <addr_>. + + virtual int protect (ssize_t len = -1, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <this->base_addr_> up to <len> bytes. If <len> == -1 + // then change protection of all pages in the mapped region. + + virtual int protect (void *addr, size_t len, int prot = PROT_RDWR); + // Change the protection of the pages of the mapped region to <prot> + // starting at <addr> up to <len> bytes. + + virtual int remap (void *addr); + // Try to extend the virtual address space so that <addr> is now + // covered by the address mapping. The method succeeds and returns + // 0 if the backing store has adequate memory to cover this address. + // Otherwise, it returns -1. This method is typically called by a + // UNIX signal handler for SIGSEGV or a Win32 structured exception + // when another process has grown the backing store (and its + // mapping) and our process now incurs a fault because our mapping + // isn't in range (yet). + + virtual void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Implement the algorithm for rounding up the request to an + // appropriate chunksize. + + virtual size_t round_up (size_t nbytes); + + virtual int commit_backing_store (size_t rounded_bytes, off_t &file_offset); + // Compute the new file_offset of the backing store and commit the + // memory. + + virtual int map_file (off_t file_offset); + // Memory map the file up to <file_offset> bytes. + + virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); + // Handle SIGSEGV and SIGBUS signals to remap shared memory + // properly. + + ACE_Sig_Handler signal_handler_; + // Handles SIGSEGV. + + ACE_Mem_Map mmap_; + // Memory-mapping object. + + void *base_addr_; + // Base of mapped region. If this has the value of 0 then the OS is + // free to select any address to map the file, otherwise this value + // is what the OS must try to use to mmap the file. + + int flags_; + // Flags passed into <ACE_OS::mmap>. + + const int write_each_page_; + // Should we write a byte to each page to forceably allocate memory + // for this backing store? + + char backing_store_[MAXPATHLEN]; + // Name of the backing store where the shared memory is kept. +}; + +class ACE_Export ACE_Lite_MMAP_Memory_Pool : public ACE_MMAP_Memory_Pool + // = TITLE + // Make a ``lighter-weight'' memory pool based <ACE_Mem_Map>. + // + // = DESCRIPTION + // This implementation allows memory to be shared between + // processes. However, unlike the <ACE_MMAP_Memory_Pool> + // the sync() methods are no-ops, which means that we don't pay + // for the price of flushing the memory to the backing store on + // every update. Naturally, this trades off increased + // performance for less reliability if the machine crashes. +{ +public: + // = Initialization and termination methods. + ACE_Lite_MMAP_Memory_Pool (const char *pool_name = 0, + int use_fixed_addr = 1, + int write_each_page = 1, + char *base_addr = ACE_DEFAULT_BASE_ADDR); + // Initialize the pool. + + int sync (ssize_t len = -1, int flags = MS_SYNC); + // Overwrite the default sync behavior with no-op + + int sync (void *addr, size_t len, int flags = MS_SYNC); + // Overwrite the default sync behavior with no-op +}; + +#if defined (__ACE_INLINE__) +#include "ace/Memory_Pool.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_MEMORY_POOL_H */ + + + + diff --git a/ace/Memory_Pool.i b/ace/Memory_Pool.i new file mode 100644 index 00000000000..cd7ce978ab7 --- /dev/null +++ b/ace/Memory_Pool.i @@ -0,0 +1,181 @@ +/* -*- C++ -*- */ +// $Id$ + +// Memory_Pool.i + +ACE_INLINE int +ACE_Local_Memory_Pool::sync (ssize_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::sync"); + return 0; +} + +ACE_INLINE int +ACE_Local_Memory_Pool::sync (void *, size_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::sync"); + return 0; +} + +ACE_INLINE int +ACE_Local_Memory_Pool::protect (ssize_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::protect"); + return 0; +} + +ACE_INLINE int +ACE_Local_Memory_Pool::protect (void *, size_t, int) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::protect"); + return 0; +} + +ACE_INLINE size_t +ACE_MMAP_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_MMAP_Memory_Pool::round_up"); + return ACE::round_to_pagesize (nbytes); +} + +// Ask system for initial chunk of local memory. + +ACE_INLINE void * +ACE_Local_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::init_acquire"); + // Note that we assume that when ACE_Local_Memory_Pool is used, + // ACE_Malloc's constructor will only get called once. If this + // assumption doesn't hold, we are in deep trouble! + + first_time = 1; + return this->acquire (nbytes, rounded_bytes); +} + +// Let the underlying new operator figure out the alignment... + +ACE_INLINE size_t +ACE_Local_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::round_up"); + return ACE::round_to_pagesize (nbytes); +} + +// No-op for now... + +ACE_INLINE int +ACE_Local_Memory_Pool::release (void) +{ + ACE_TRACE ("ACE_Local_Memory_Pool::release"); + return 0; +} + +#if !defined (ACE_LACKS_SYSV_SHMEM) +// Implement the algorithm for rounding up the request to an +// appropriate chunksize. + +ACE_INLINE size_t +ACE_Shared_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::round_up"); + if (nbytes < ACE_DEFAULT_SEGMENT_SIZE) + nbytes = ACE_DEFAULT_SEGMENT_SIZE; + + return ACE::round_to_pagesize (nbytes); +} + +ACE_INLINE int +ACE_Shared_Memory_Pool::sync (ssize_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); + return 0; +} + +ACE_INLINE int +ACE_Shared_Memory_Pool::sync (void *, size_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::sync"); + return 0; +} + +ACE_INLINE int +ACE_Shared_Memory_Pool::protect (ssize_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); + return 0; +} + +ACE_INLINE int +ACE_Shared_Memory_Pool::protect (void *, size_t, int) +{ + ACE_TRACE ("ACE_Shared_Memory_Pool::protect"); + return 0; +} +#endif /* !ACE_LACKS_SYSV_SHMEM */ + +#if !defined (ACE_LACKS_SBRK) + +// Ask system for initial chunk of local memory. + +ACE_INLINE void * +ACE_Sbrk_Memory_Pool::init_acquire (size_t nbytes, + size_t &rounded_bytes, + int &first_time) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::init_acquire"); + // Note that we assume that when ACE_Sbrk_Memory_Pool is used, + // ACE_Malloc's constructor will only get called once. If this + // assumption doesn't hold, we are in deep trouble! + + first_time = 1; + return this->acquire (nbytes, rounded_bytes); +} + +// Round up the request to a multiple of the page size. + +ACE_INLINE size_t +ACE_Sbrk_Memory_Pool::round_up (size_t nbytes) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::round_up"); + return ACE::round_to_pagesize (nbytes); +} + +/* No-op for now... */ + +ACE_INLINE int +ACE_Sbrk_Memory_Pool::release (void) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::release"); + return 0; +} + +ACE_INLINE int +ACE_Sbrk_Memory_Pool::sync (ssize_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync"); + return 0; +} + +ACE_INLINE int +ACE_Sbrk_Memory_Pool::sync (void *, size_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::sync"); + return 0; +} + +ACE_INLINE int +ACE_Sbrk_Memory_Pool::protect (ssize_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect"); + return 0; +} + +ACE_INLINE int +ACE_Sbrk_Memory_Pool::protect (void *, size_t, int) +{ + ACE_TRACE ("ACE_Sbrk_Memory_Pool::protect"); + return 0; +} +#endif /* !ACE_LACKS_SBRK */ diff --git a/ace/Message_Block.cpp b/ace/Message_Block.cpp new file mode 100644 index 00000000000..c8266dae728 --- /dev/null +++ b/ace/Message_Block.cpp @@ -0,0 +1,249 @@ +// Message_Block.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Message_Block.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Message_Block.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Message_Block) + +int +ACE_Message_Block::copy (const char *buf, size_t n) +{ + ACE_TRACE ("ACE_Message_Block::copy"); + // Note that for this to work correct, end() *must* be >= wr_ptr(). + size_t len = size_t (this->end () - this->wr_ptr ()); + + if (len < n) + return -1; + else + { + (void) ACE_OS::memcpy (this->wr_ptr (), buf, n); + this->wr_ptr (n); + return 0; + } +} + +void +ACE_Message_Block::dump (void) const +{ + ACE_TRACE ("ACE_Message_Block::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, + "-----( Message Block )-----\n" + "type = %d\n" + "priority = %d\n" + "max_size = %d\n" + "cur_size = %d\n" + "flag = %x\n" + "next = %u\n" + "base = %u\n" + "rd_ptr = %u\n" + "wr_ptr = %u\n" + "---------------------------\n", + this->type_, this->priority_, this->max_size_, this->cur_size_, + this->flags_, this->next_, this->base_, this->rd_ptr_, + this->wr_ptr_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Message_Block::ACE_Message_Block (void) + : flags_ (0), + base_ (0), + cur_size_ (0), + max_size_ (0), + rd_ptr_ (0), + wr_ptr_ (0), + type_ (MB_NORMAL), + priority_ (0), + cont_ (0), + next_ (0), + prev_ (0), + allocator_ (0) +{ + ACE_TRACE ("ACE_Message_Block::ACE_Message_Block"); +} + +ACE_Message_Block::ACE_Message_Block (size_t sz, + ACE_Message_Type msg_type, + ACE_Message_Block *msg_cont, + const char *msg_data, + ACE_Allocator *alloc) +{ + ACE_TRACE ("ACE_Message_Block::ACE_Message_Block"); + if (this->init (sz, msg_type, msg_cont, msg_data, alloc) == -1) + ACE_ERROR ((LM_ERROR, "ACE_Message_Block")); +} + +ACE_Message_Block::~ACE_Message_Block (void) +{ + ACE_TRACE ("ACE_Message_Block::~ACE_Message_Block"); + if (ACE_BIT_DISABLED (this->flags_, ACE_Message_Block::DONT_DELETE)) + { + if (this->allocator_) + this->allocator_->free ((void *) this->base_); + else + delete [] this->base_; + } + if (this->cont_) + delete this->cont_; + this->prev_ = 0; + this->next_ = 0; +} + +ACE_Message_Block::ACE_Message_Block (const char *data, + size_t size) + : flags_ (ACE_Message_Block::DONT_DELETE), + base_ ((char *) data), + cur_size_ (size), + max_size_ (size), + rd_ptr_ (0), + wr_ptr_ (0), + type_ (MB_NORMAL), + priority_ (0), + cont_ (0), + next_ (0), + prev_ (0), + allocator_ (0) +{ + ACE_TRACE ("ACE_Message_Block::ACE_Message_Block"); +} + +int +ACE_Message_Block::size (size_t length) +{ + ACE_TRACE ("ACE_Message_Block::size"); + if (length < this->max_size_) + this->cur_size_ = length; + else + { + int r_delta, w_delta; + char *buf; + + if (this->allocator_ == 0) + ACE_NEW_RETURN (buf, char[length], -1); + else // Use the allocator! + { + buf = (char *) this->allocator_->malloc (length); + if (buf == 0) + { + errno = ENOMEM; + return -1; + } + } + + if (ACE_BIT_DISABLED (this->flags_, ACE_Message_Block::DONT_DELETE)) + { + if (this->allocator_) + this->allocator_->free ((void *) this->base_); + else + delete [] this->base_; + } + else + // We now assume ownership. + ACE_CLR_BITS (this->flags_, ACE_Message_Block::DONT_DELETE); + + ACE_OS::memcpy (buf, this->base_, this->cur_size_); + r_delta = this->rd_ptr_ - this->base_; + w_delta = this->wr_ptr_ - this->base_; + this->max_size_ = length; + this->cur_size_ = length; + + this->base_ = buf; + + this->rd_ptr_ = this->base_ + r_delta; + this->wr_ptr_ = this->base_ + w_delta; + } + return 0; +} + +int +ACE_Message_Block::init (const char *data, + size_t size) +{ + ACE_TRACE ("ACE_Message_Block::init"); + this->base_ = (char *) data; + this->cur_size_ = size; + this->max_size_ = size; + ACE_SET_BITS (this->flags_, ACE_Message_Block::DONT_DELETE); + return 0; +} + +int +ACE_Message_Block::init (size_t sz, + ACE_Message_Type msg_type, + ACE_Message_Block *msg_cont, + const char *msg_data, + ACE_Allocator *allocator) +{ + ACE_TRACE ("ACE_Message_Block::init"); + this->flags_ = 0; + + if (msg_data == 0) + { + if (allocator == 0) + { + this->allocator_ = 0; + ACE_NEW_RETURN (this->base_, char[sz], -1); + } + else // Use the allocator! + { + this->allocator_ = allocator; + this->base_ = (char *) allocator->malloc (sz); + if (this->base_ == 0) + { + errno = ENOMEM; + return -1; + } + } + } + else + { + this->base_ = (char *) msg_data; + ACE_SET_BITS (this->flags_, ACE_Message_Block::DONT_DELETE); + } + + this->cur_size_ = sz; + this->max_size_ = sz; + this->rd_ptr_ = this->base_; + this->wr_ptr_ = this->base_; + this->priority_ = 0; + this->type_ = msg_type; + this->cont_ = msg_cont; + this->next_ = 0; + this->prev_ = 0; + return 0; +} + +ACE_Message_Block * +ACE_Message_Block::clone (Message_Flags mask) const +{ + // You always want to clear this one to prevent memory leaks but you + // might add some others later. + const Message_Flags always_clear = ACE_Message_Block::DONT_DELETE; + + ACE_TRACE ("ACE_Message_Block::clone"); + ACE_Message_Block *nb; + + ACE_NEW_RETURN (nb, + ACE_Message_Block (this->max_size_, this->type_, + 0, 0, this->allocator_), + 0); + + ACE_OS::memcpy (nb->base_, this->base_, this->max_size_); + + nb->rd_ptr (this->rd_ptr_ - this->base_); + nb->wr_ptr (this->wr_ptr_ - this->base_); + + // Set new flags minus the mask... + nb->set_flags (this->flags ()); + nb->clr_flags (mask | always_clear); + + if (this->cont_ != 0) + nb->cont_ = this->cont_->clone (mask); + return nb; +} diff --git a/ace/Message_Block.h b/ace/Message_Block.h new file mode 100644 index 00000000000..c94fbfffc81 --- /dev/null +++ b/ace/Message_Block.h @@ -0,0 +1,268 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Message_Block.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#include "ace/ACE.h" + +#if !defined (ACE_MESSAGE_BLOCK_H) +#define ACE_MESSAGE_BLOCK_H + +#include "ace/Malloc.h" + +class ACE_Export ACE_Message_Block + // = TITLE + // Object used to store messages in the ASX framework. + // + // = DESCRIPTION + // An ACE_Message_Block is modeled after the message data + // structures used in System V STREAMS. A Message_Block is + // composed of one or more Message_Blocks that are linked + // together by PREV and NEXT pointers. In addition, a + // ACE_Message_Block may also be linked to a chain of other + // Message_Blocks. This structure enables efficient + // manipulation of arbitrarily-large messages *without* + // incurring memory copying overhead. +{ +public: + enum ACE_Message_Type + { + // = Data and protocol messages (regular and priority) + MB_DATA = 0x01, // regular data + MB_PROTO = 0x02, // protocol control + + // = Control messages (regular and priority) + MB_BREAK = 0x03, // line break + MB_PASSFP = 0x04, // pass file pointer + MB_EVENT = 0x05, // post an event to an event queue + MB_SIG = 0x06, // generate process signal + MB_IOCTL = 0x07, // ioctl; set/get params + MB_SETOPTS = 0x08, // set various stream head options + + // = Control messages (high priority; go to head of queue) + MB_IOCACK = 0x81, // acknowledge ioctl + MB_IOCNAK = 0x82, // negative ioctl acknowledge + MB_PCPROTO = 0x83, // priority proto message + MB_PCSIG = 0x84, // generate process signal + MB_READ = 0x85, // generate read notification + MB_FLUSH = 0x86, // flush your queues + MB_STOP = 0x87, // stop transmission immediately + MB_START = 0x88, // restart transmission after stop + MB_HANGUP = 0x89, // line disconnect + MB_ERROR = 0x8a, // fatal error used to set u.u_error + MB_PCEVENT = 0x8b, // post an event to an event queue + + // Message class masks + MB_NORMAL = 0x00, // Normal priority messages + MB_PRIORITY = 0x80, // High priority control messages + MB_USER = 0x200 // User-defined control messages + }; + + typedef u_long Message_Flags; + + enum + { + DONT_DELETE = 01, // Don't delete the data on exit since we don't own it. + USER_FLAGS = 0x1000 // user defined flags start here + }; + + // = Initialization and termination. + ACE_Message_Block (void); + // Create an empty message. + + ACE_Message_Block (const char *data, + size_t size = 0); + // Create a Message Block that assumes ownership of <data> without + // copying it (i.e., we don't delete it since we don't malloc it!). + + ACE_Message_Block (size_t size, + ACE_Message_Type type = MB_DATA, + ACE_Message_Block *cont = 0, + const char *data = 0, + ACE_Allocator *allocator = 0); + // Create an initialized message of type <type> containing <size> + // bytes. The <cont> argument initializes the continuation field in + // the <Message_Block>. If <data> == 0 then we create and own the + // <data>, using <allocator> to get the data if it's non-0. If + // <data> != 0 we assume ownership of the <data> (and don't delete + // it). + + int init (const char *data, + size_t size = 0); + // Create a Message Block that assumes ownership of <data> (i.e., + // doesn't delete it since it didn't malloc it!). + + int init (size_t size, + ACE_Message_Type type = MB_DATA, + ACE_Message_Block *cont = 0, + const char *data = 0, + ACE_Allocator *allocator = 0); + // Create an initialized message of type <type> containing <size> + // bytes. The <cont> argument initializes the continuation field in + // the <Message_Block>. If <data> == 0 then we create and own the + // <data>, using <allocator> to get the data if it's non-0. If + // <data> != 0 we assume ownership of the <data> (and don't delete + // it). + + ~ACE_Message_Block (void); + // Delete all the resources held in the message. + + int is_data_msg (void) const; + // Find out what type of message this is. + + ACE_Message_Type msg_class (void) const; + // Find out what class of message this is (there are two classes, + // <normal> messages and <high-priority> messages). + + ACE_Message_Type msg_type (void) const; + // Get type of the message. + + // = Set/Unset/Inspect the message flags. + Message_Flags set_flags (Message_Flags more_flags); + Message_Flags clr_flags (Message_Flags less_flags); + Message_Flags flags (void) const; + + void msg_type (ACE_Message_Type type); + // Set type of the message. + + u_long msg_priority (void) const; + // Get priority of the message. + + void msg_priority (u_long priority); + // Set priority of the message. + + ACE_Message_Block *clone (Message_Flags mask = ACE_Message_Block::DONT_DELETE) const; + // Return an exact "deep copy" of the message. + + // = Operations on Message data + + int copy (const char *buf, size_t n); + // Copies <n> bytes from <buf> into the Message_Block starting at + // the wr_ptr() offset. Return 0 if succeeds and -1 if the size of + // the message is too small... + + char *base (void) const; + // Get message data. + + void base (char *data, size_t size, Message_Flags = DONT_DELETE); + // Set message data. + + char *end (void) const; + // Return a pointer to 1 past the end of the data in a message. + + char *rd_ptr (void); + // Get the read pointer. + void rd_ptr (char *ptr); + // Set the read pointer to <ptr>. + void rd_ptr (size_t n); + // Set the read pointer ahead <n> bytes. + + char *wr_ptr (void); + // Get the write pointer. + void wr_ptr (char *ptr); + // Set the write pointer to <ptr>. + void wr_ptr (size_t n); + // Set the write pointer ahead <n> bytes. + + // = The length of a message is computed as the length between the + // wr_ptr() - rd_ptr ()). + size_t length (void) const; + // Get the length of the message + void length (size_t n); + // Set the length of the message + + // = The size of the allocated buffer is the total amount of space + // alloted. + size_t size (void) const; + // Get the total amount of space in the message. + int size (size_t length); + // Set the total amount of space in the message. Returns 0 if + // successful, else -1. + + // = The coninuation field is used to chain together composite + // messages. + ACE_Message_Block *cont (void) const; + // Get the continuation field. + void cont (ACE_Message_Block *); + // Set the continuation field. + + // = The <next_> pointer points to the <Message_Block> directly ahead + // in the Message_Queue. + ACE_Message_Block *next (void) const; + // Get link to next message. + void next (ACE_Message_Block *); + // Set link to next message. + + // = The <prev_> pointer points to the <Message_Block> directly + // ahead in the Message_Queue. + ACE_Message_Block *prev (void) const; + // Get link to prev message. + void prev (ACE_Message_Block *); + // Set link to prev message. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + Message_Flags flags_; + // Misc flags. + + char *base_; + // Pointer to beginning of message block. + + size_t cur_size_; + // Current size of message block. + + size_t max_size_; + // Total size of buffer. + + char *rd_ptr_; + // Pointer to beginning of next read. + + char *wr_ptr_; + // Pointer to beginning of next write. + + ACE_Message_Type type_; + // Type of message. + + u_long priority_; + // Priority of message. + + // = Links to other ACE_Message_Block *s. + ACE_Message_Block *cont_; + // Pointer to next message block in the chain. + + ACE_Message_Block *next_; + // Pointer to next message in the list. + + ACE_Message_Block *prev_; + // Pointer to previous message in the list. + + ACE_Allocator *allocator_; + // Pointer to the allocator defined for this message block. + + // = Disallow these operations for now (use <clone> instead). + ACE_Message_Block &operator= (const ACE_Message_Block &); + ACE_Message_Block (const ACE_Message_Block &); +}; + +#if defined (__ACE_INLINE__) +#include "ace/Message_Block.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_MESSAGE_BLOCK_H */ diff --git a/ace/Message_Block.i b/ace/Message_Block.i new file mode 100644 index 00000000000..ee7f50939b8 --- /dev/null +++ b/ace/Message_Block.i @@ -0,0 +1,234 @@ +/* -*- C++ -*- */ +// $Id$ + +// Message_Block.i + +#include "ace/Log_Msg.h" + +ACE_INLINE ACE_Message_Block::Message_Flags +ACE_Message_Block::set_flags (ACE_Message_Block::Message_Flags more_flags) +{ + ACE_TRACE ("ACE_Message_Block::set_flags"); + // Later we might mask more_glags so that user can't change internal + // ones: more_flags &= ~(USER_FLAGS -1). + return ACE_SET_BITS (this->flags_, more_flags); +} + +ACE_INLINE ACE_Message_Block::Message_Flags +ACE_Message_Block::clr_flags (ACE_Message_Block::Message_Flags less_flags) +{ + ACE_TRACE ("ACE_Message_Block::clr_flags"); + // Later we might mask more_flags so that user can't change internal + // ones: less_flags &= ~(USER_FLAGS -1). + return ACE_CLR_BITS (this->flags_, less_flags); +} + +ACE_INLINE ACE_Message_Block::Message_Flags +ACE_Message_Block::flags (void) const +{ + ACE_TRACE ("ACE_Message_Block::flags"); + return this->flags_; +} + +/* Return the length of the "active" portion of the message */ + +ACE_INLINE size_t +ACE_Message_Block::length (void) const +{ + ACE_TRACE ("ACE_Message_Block::length"); + return this->wr_ptr_ - this->rd_ptr_; +} + +// Sets the length of the "active" portion of the message. This is +// defined as the offset from RD_PTR to WR_PTR. + +ACE_INLINE void +ACE_Message_Block::length (size_t len) +{ + ACE_TRACE ("ACE_Message_Block::length"); + this->wr_ptr_ = this->rd_ptr_ + len; +} + +// Return the length of the potential size of the message. + +ACE_INLINE size_t +ACE_Message_Block::size (void) const +{ + ACE_TRACE ("ACE_Message_Block::size"); + return this->cur_size_; +} + +ACE_INLINE ACE_Message_Block & +ACE_Message_Block::operator= (const ACE_Message_Block &) +{ + ACE_TRACE ("ACE_Message_Block::operator="); + return *this; +} + +ACE_INLINE ACE_Message_Block::ACE_Message_Type +ACE_Message_Block::msg_type (void) const +{ + ACE_TRACE ("ACE_Message_Block::msg_type"); + return this->type_; +} + +ACE_INLINE void +ACE_Message_Block::msg_type (ACE_Message_Block::ACE_Message_Type t) +{ + ACE_TRACE ("ACE_Message_Block::msg_type"); + this->type_ = t; +} + +ACE_INLINE ACE_Message_Block::ACE_Message_Type +ACE_Message_Block::msg_class (void) const +{ + ACE_TRACE ("ACE_Message_Block::msg_class"); + + if (this->msg_type () < ACE_Message_Block::MB_PRIORITY) + return ACE_Message_Block::MB_NORMAL; + else if (this->msg_type () < ACE_Message_Block::MB_USER) + return ACE_Message_Block::MB_PRIORITY; + else + return ACE_Message_Block::MB_USER; +} + +ACE_INLINE int +ACE_Message_Block::is_data_msg (void) const +{ + ACE_TRACE ("ACE_Message_Block::is_data_msg"); + ACE_Message_Type mt = this->msg_type (); + return + mt == ACE_Message_Block::MB_DATA + || mt == ACE_Message_Block::MB_PROTO + || mt == ACE_Message_Block::MB_PCPROTO; +} + +ACE_INLINE u_long +ACE_Message_Block::msg_priority (void) const +{ + ACE_TRACE ("ACE_Message_Block::msg_priority"); + return this->priority_; +} + +ACE_INLINE void +ACE_Message_Block::msg_priority (u_long pri) +{ + ACE_TRACE ("ACE_Message_Block::msg_priority"); + this->priority_ = pri; +} + +ACE_INLINE void +ACE_Message_Block::base (char *msg_data, + size_t msg_length, + Message_Flags msg_flags) +{ + ACE_TRACE ("ACE_Message_Block::base"); + this->max_size_ = msg_length; + this->cur_size_ = msg_length; + this->rd_ptr_ = msg_data; + this->wr_ptr_ = msg_data; + this->base_ = msg_data; + this->flags_ = msg_flags; +} + +ACE_INLINE char * +ACE_Message_Block::rd_ptr (void) +{ + ACE_TRACE ("ACE_Message_Block::rd_ptr"); + return this->rd_ptr_; +} + +ACE_INLINE void +ACE_Message_Block::wr_ptr (char *new_ptr) +{ + ACE_TRACE ("ACE_Message_Block::wr_ptr"); + this->wr_ptr_ = new_ptr; +} + +ACE_INLINE char * +ACE_Message_Block::base (void) const +{ + ACE_TRACE ("ACE_Message_Block::base"); + return this->base_; +} + +// Return a pointer to 1 past the end of the data buffer. + +ACE_INLINE char * +ACE_Message_Block::end (void) const +{ + ACE_TRACE ("ACE_Message_Block::end"); + return this->base_ + this->max_size_; +} + + +ACE_INLINE void +ACE_Message_Block::rd_ptr (char *new_ptr) +{ + ACE_TRACE ("ACE_Message_Block::rd_ptr"); + this->rd_ptr_ = new_ptr; +} + +ACE_INLINE void +ACE_Message_Block::rd_ptr (size_t n) +{ + ACE_TRACE ("ACE_Message_Block::rd_ptr"); + this->rd_ptr_ += n; +} + +ACE_INLINE char * +ACE_Message_Block::wr_ptr (void) +{ + ACE_TRACE ("ACE_Message_Block::wr_ptr"); + return this->wr_ptr_; +} + +ACE_INLINE void +ACE_Message_Block::wr_ptr (size_t n) +{ + ACE_TRACE ("ACE_Message_Block::wr_ptr"); + this->wr_ptr_ += n; +} + +ACE_INLINE void +ACE_Message_Block::cont (ACE_Message_Block *next_block) +{ + ACE_TRACE ("ACE_Message_Block::cont"); + this->cont_ = next_block; +} + +ACE_INLINE ACE_Message_Block * +ACE_Message_Block::cont (void) const +{ + ACE_TRACE ("ACE_Message_Block::cont"); + return this->cont_; +} + +ACE_INLINE void +ACE_Message_Block::next (ACE_Message_Block *next_block) +{ + ACE_TRACE ("ACE_Message_Block::next"); + this->next_ = next_block; +} + +ACE_INLINE ACE_Message_Block * +ACE_Message_Block::next (void) const +{ + ACE_TRACE ("ACE_Message_Block::next"); + return this->next_; +} + +ACE_INLINE void +ACE_Message_Block::prev (ACE_Message_Block *next_block) +{ + ACE_TRACE ("ACE_Message_Block::prev"); + this->prev_ = next_block; +} + +ACE_INLINE ACE_Message_Block * +ACE_Message_Block::prev (void) const +{ + ACE_TRACE ("ACE_Message_Block::prev"); + return this->prev_; +} + diff --git a/ace/Message_Queue.cpp b/ace/Message_Queue.cpp new file mode 100644 index 00000000000..30b8a77abaa --- /dev/null +++ b/ace/Message_Queue.cpp @@ -0,0 +1,508 @@ +// Message_Queue.cpp +// $Id$ + +#if !defined (ACE_MESSAGE_QUEUE_C) +#define ACE_MESSAGE_QUEUE_C + +#define ACE_BUILD_DLL +#include "ace/Message_Queue.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Message_Queue.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Message_Queue) + +template <ACE_SYNCH_1> void +ACE_Message_Queue<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, + "deactivated = %d\n" + "low_water_mark = %d\n" + "high_water_mark = %d\n" + "cur_bytes = %d\n" + "cur_count = %d\n", + this->deactivated_, + this->low_water_mark_, + this->high_water_mark_, + this->cur_bytes_, + this->cur_count_)); + ACE_DEBUG ((LM_DEBUG,"notfull_cond: \n")); + notfull_cond_.dump(); + ACE_DEBUG ((LM_DEBUG,"notempty_cond: \n")); + notempty_cond_.dump(); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <ACE_SYNCH_1> +ACE_Message_Queue<ACE_SYNCH_2>::ACE_Message_Queue (size_t hwm, + size_t lwm) + : notfull_cond_ (this->lock_), + notempty_cond_ (this->lock_) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::ACE_Message_Queue"); + if (this->open (hwm, lwm) == -1) + ACE_ERROR ((LM_ERROR, "open")); +} + +template <ACE_SYNCH_1> +ACE_Message_Queue<ACE_SYNCH_2>::~ACE_Message_Queue (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::~ACE_Message_Queue"); + if (this->head_ != 0) + if (this->close () == -1) + ACE_ERROR ((LM_ERROR, "close")); +} + +// Don't bother locking since if someone calls this function more than +// once for the same queue, we're in bigger trouble than just +// concurrency control! + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::open (size_t hwm, size_t lwm) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::open"); + this->high_water_mark_ = hwm; + this->low_water_mark_ = lwm; + this->deactivated_ = 0; + this->cur_bytes_ = 0; + this->cur_count_ = 0; + this->tail_ = 0; + this->head_ = 0; + return 0; +} + +// Implementation of the public deactivate() method +// (assumes locks are held). + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::deactivate_i (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::deactivate_i"); + int current_status = + this->deactivated_ ? WAS_INACTIVE : WAS_ACTIVE; + + // Wakeup all waiters. + this->notempty_cond_.broadcast (); + this->notfull_cond_.broadcast (); + + this->deactivated_ = 1; + return current_status; +} + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::activate_i (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::activate_i"); + int current_status = + this->deactivated_ ? WAS_INACTIVE : WAS_ACTIVE; + this->deactivated_ = 0; + return current_status; +} + +// Clean up the queue if we have not already done so! + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::close (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::close"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + int res = this->deactivate_i (); + + // Free up the remaining message on the list + + for (this->tail_ = 0; this->head_ != 0; ) + { + ACE_Message_Block *temp; + + // Make sure we decrement all the counts. + for (temp = this->head_; + temp != 0; + temp = temp->cont ()) + this->cur_bytes_ -= temp->size (); + + this->cur_count_--; + + this->head_ = this->head_->next (); + delete temp; + } + + return res; +} + +// Actually put the node at the end (no locking so must be called with +// locks held). + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::enqueue_tail_i (ACE_Message_Block *new_item) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::enqueue_tail_i"); + + if (new_item == 0) + return -1; + + // List was empty, so build a new one. + if (this->tail_ == 0) + { + this->head_ = new_item; + this->tail_ = new_item; + new_item->next (0); + new_item->prev (0); + } + // Link at the end. + else + { + + new_item->next (0); + this->tail_->next (new_item); + new_item->prev (this->tail_); + this->tail_ = new_item; + } + + // Make sure to count *all* the bytes in a composite message!!! + + for (ACE_Message_Block *temp = new_item; + temp != 0; + temp = temp->cont ()) + this->cur_bytes_ += temp->size (); + + this->cur_count_++; + + // Tell any blocked threads that the queue has a new item! + if (this->notempty_cond_.signal () != 0) + return -1; + else + return this->cur_count_; +} + +// Actually put the node at the head (no locking) + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::enqueue_head_i (ACE_Message_Block *new_item) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::enqueue_head_i"); + + if (new_item == 0) + return -1; + + new_item->prev (0); + new_item->next (this->head_); + + if (this->head_ != 0) + this->head_->prev (new_item); + else + this->tail_ = new_item; + + this->head_ = new_item; + + // Make sure to count *all* the bytes in a composite message!!! + + for (ACE_Message_Block *temp = new_item; + temp != 0; + temp = temp->cont ()) + this->cur_bytes_ += temp->size (); + + this->cur_count_++; + + // Tell any blocked threads that the queue has a new item! + if (this->notempty_cond_.signal () != 0) + return -1; + else + return this->cur_count_; +} + +// Actually put the node at its proper position relative to its +// priority. + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::enqueue_i (ACE_Message_Block *new_item) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::enqueue_i"); + + if (new_item == 0) + return -1; + + if (this->head_ == 0) + // Check for simple case of an empty queue, where all we need to + // do is insert <new_item> into the head. + return this->enqueue_head_i (new_item); + else + { + ACE_Message_Block *temp; + + // Figure out where the new item goes relative to its priority. + // We start looking from the highest priority to the lowest + // priority. + + for (temp = this->tail_; + temp != 0; + temp = temp->prev ()) + { + if (temp->msg_priority () >= new_item->msg_priority ()) + // Break out when we've located an item that has higher + // priority that <new_item>. + break; + } + + if (temp == 0) + // Check for simple case of inserting at the head of the queue, + // where all we need to do is insert <new_item> before the + // current head. + return this->enqueue_head_i (new_item); + else if (temp->next () == 0) + // Check for simple case of inserting at the end of the + // queue, where all we need to do is insert <new_item> after + // the current tail. + return this->enqueue_tail_i (new_item); + else + { + // Insert the message right before the item of equal or + // higher priority. This ensures that FIFO order is + // maintained when messages of the same priority are + // inserted consecutively. + new_item->prev (temp); + new_item->next (temp->next ()); + temp->next ()->prev (new_item); + temp->next (new_item); + } + } + + // Make sure to count *all* the bytes in a composite message!!! + + for (ACE_Message_Block *temp = new_item; + temp != 0; + temp = temp->cont ()) + this->cur_bytes_ += temp->size (); + + this->cur_count_++; + + // Tell any blocked threads that the queue has a new item! + if (this->notempty_cond_.signal () != 0) + return -1; + else + return this->cur_count_; +} + +// Actually get the first ACE_Message_Block (no locking, so must be called +// with locks held). This method assumes that the queue has at least +// one item in it when it is called. + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::dequeue_head_i (ACE_Message_Block *&first_item) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::dequeue_head_i"); + first_item = this->head_; + this->head_ = this->head_->next (); + + if (this->head_ == 0) + this->tail_ = 0; + else + // The prev pointer of the first message block has to point to + // NULL... + this->head_->prev (0); + + // Make sure to subtract off all of the bytes associated with this + // message. + for (ACE_Message_Block *temp = first_item; + temp != 0; + temp = temp->cont ()) + this->cur_bytes_ -= temp->size (); + + this->cur_count_--; + +#if 0 + if (this->cur_bytes_ <= this->low_water_mark_) + // If queue is no longer full signal any waiting threads. +#endif /* 0 */ + + if (this->notfull_cond_.signal () != 0) + return -1; + else + return this->cur_count_; +} + +// Take a look at the first item without removing it. + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::peek_dequeue_head (ACE_Message_Block *&first_item, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::peek_dequeue_head"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + + // Wait for at least one item to become available + + while (this->is_empty_i ()) + { + if (this->notempty_cond_.wait (tv) == -1) + { + if (errno == ETIME) + errno = EWOULDBLOCK; + return -1; + } + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + } + + first_item = this->head_; + return this->cur_count_; +} + +// Block indefinitely waiting for an item to arrive, +// does not ignore alerts (e.g., signals). + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::enqueue_head (ACE_Message_Block *new_item, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::enqueue_head"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + + // Wait while the queue is full + + while (this->is_full_i ()) + { + if (this->notfull_cond_.wait (tv) == -1) + { + if (errno == ETIME) + errno = EWOULDBLOCK; + return -1; + } + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + } + return this->enqueue_head_i (new_item); +} + +// Enqueue an <ACE_Message_Block *> into the <Message_Queue> in +// accordance with its <msg_priority> (0 is lowest priority). Returns +// -1 on failure, else the number of items still on the queue. + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::enqueue (ACE_Message_Block *new_item, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::enqueue"); + + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + + // Wait while the queue is full + + while (this->is_full_i ()) + { + if (this->notfull_cond_.wait (tv) == -1) + { + if (errno == ETIME) + errno = EWOULDBLOCK; + return -1; + } + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + } + + return this->enqueue_i (new_item); +} + +// Block indefinitely waiting for an item to arrive, +// does not ignore alerts (e.g., signals). + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::enqueue_tail (ACE_Message_Block *new_item, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::enqueue_tail"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + + // Wait while the queue is full + + while (this->is_full_i ()) + { + if (this->notfull_cond_.wait (tv) == -1) + { + if (errno == ETIME) + errno = EWOULDBLOCK; + return -1; + } + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + } + return this->enqueue_tail_i (new_item); +} + +// Remove an item from the front of the queue. If TV == 0 block +// indefinitely (or until an alert occurs). Otherwise, block for upto +// the amount of time specified by TV. + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::dequeue_head (ACE_Message_Block *&first_item, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::dequeue_head"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + + // Wait while the queue is empty. + + while (this->is_empty_i ()) + { + if (this->notempty_cond_.wait (tv) == -1) + { + if (errno == ETIME) + errno = EWOULDBLOCK; + return -1; + } + if (this->deactivated_) + { + errno = ESHUTDOWN; + return -1; + } + } + + return this->dequeue_head_i (first_item); +} + +#endif /* ACE_MESSAGE_QUEUE_C */ diff --git a/ace/Message_Queue.h b/ace/Message_Queue.h new file mode 100644 index 00000000000..1caac7f3d0a --- /dev/null +++ b/ace/Message_Queue.h @@ -0,0 +1,217 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Message_Queue.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_MESSAGE_LIST_H) +#define ACE_MESSAGE_LIST_H + +#include "ace/Message_Block.h" +#include "ace/Time_Value.h" +#include "ace/IO_Cntl_Msg.h" + +template <ACE_SYNCH_1> +class ACE_Message_Queue + // = TITLE + // A thread-safe message queueing facility, modeled after the + // queueing facilities in System V StreamS. + // + // = DESCRIPTION + // A ACE_Message_Queue is the central queueing facility for + // messages in the ASX framework. If <ACE_SYNCH_1> is + // ACE_MT_SYNCH then all operations are thread-safe. Otherwise, + // if it's <ACE_NULL_SYNCH> then there's no locking overhead. +{ +public: + // = Default high and low water marks. + enum + { + DEFAULT_LWM = 0, + // Default low watermark. + DEFAULT_HWM = 16 * 1024, + // Default high watermark (16 K). + WAS_ACTIVE = 1, + // Message queue was active before activate() or deactivate(). + WAS_INACTIVE = 2 + // Message queue was inactive before activate() or deactivate(). + }; + + // = Initialization and termination methods. + ACE_Message_Queue (size_t hwm = DEFAULT_HWM, + size_t lwm = DEFAULT_LWM); + // Create a message queue with all the defaults. + int open (size_t hwm = DEFAULT_HWM, size_t lwm = DEFAULT_LWM); + // Create a message queue with all the defaults. + + int close (void); + // Close down the message queue and release all resources. + + ~ACE_Message_Queue (void); + // Close down the message queue and release all resources. + + int peek_dequeue_head (ACE_Message_Block *&first_item, + ACE_Time_Value *tv = 0); + // Retrieve the first ACE_Message_Block without removing it. + // Returns -1 on failure, else the number of items still on the + // queue. + + // = For all the following three routines if tv == 0, the caller + // will block until action is possible, else will wait for amount of + // time in *tv). Calls will return, however, when queue is closed, + // deactivated, when a signal occurs, or if the time specified in tv + // elapses, (in which case errno = EWOULDBLOCK). + + int enqueue (ACE_Message_Block *new_item, ACE_Time_Value *tv = 0); + // Enqueue an <ACE_Message_Block *> into the <Message_Queue> in + // accordance with its <msg_priority> (0 is lowest priority). FIFO + // order is maintained when messages of the same priority are + // inserted consecutively. Returns -1 on failure, else the number + // of items still on the queue. + + int enqueue_tail (ACE_Message_Block *new_item, ACE_Time_Value *tv = 0); + // Enqueue an <ACE_Message_Block *> at the end of the queue. + // Returns -1 on failure, else the number of items still on the + // queue. + + int enqueue_head (ACE_Message_Block *new_item, ACE_Time_Value *tv = 0); + // Enqueue an <ACE_Message_Block *> at the head of the queue. + // Returns -1 on failure, else the number of items still on the + // queue. + + int dequeue_head (ACE_Message_Block *&first_item, ACE_Time_Value *tv = 0); + // Dequeue and return the <ACE_Message_Block *> at the head of the + // queue. Returns -1 on failure, else the number of items still on + // the queue. + + // = Checks if queue is full/empty. + int is_full (void); + // True if queue is full, else false. + int is_empty (void); + // True if queue is empty, else false. + + size_t message_bytes (void); + // Number of total bytes on the queue. + + size_t message_count (void); + // Number of total messages on the queue. + + // = Flow control routines + + size_t high_water_mark (void); + // Get high watermark. + void high_water_mark (size_t hwm); + // Set high watermark. + size_t low_water_mark (void); + // Get low watermark. + void low_water_mark (size_t lwm); + // Set low watermark. + + // = Activation control methods. + + int deactivate (void); + // Deactivate the queue and wakeup all threads waiting on the queue + // so they can continue. No messages are removed from the queue, + // however. Any other operations called until the queue is + // activated again will immediately return -1 with <errno> == + // ESHUTDOWN. Returns WAS_INACTIVE if queue was inactive before the + // call and WAS_ACTIVE if queue was active before the call. + + int activate (void); + // Reactivate the queue so that threads can enqueue and dequeue + // messages again. Returns WAS_INACTIVE if queue was inactive + // before the call and WAS_ACTIVE if queue was active before the + // call. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Routines that actually do the enqueueing and dequeueing (these + // assume that locks are held by the corresponding public methods). + + int enqueue_i (ACE_Message_Block *new_item); + // Enqueue an <ACE_Message_Block *> in accordance with its priority. + + int enqueue_tail_i (ACE_Message_Block *new_item); + // Enqueue an <ACE_Message_Block *> at the end of the queue. + + int enqueue_head_i (ACE_Message_Block *new_item); + // Enqueue an <ACE_Message_Block *> at the head of the queue. + + int dequeue_head_i (ACE_Message_Block *&first_item); + // Dequeue and return the <ACE_Message_Block *> at the head of the + // queue. + + // = Check the boundary conditions (assumes locks are held). + int is_full_i (void); + // True if queue is full, else false. + int is_empty_i (void); + // True if queue is empty, else false. + + // = Implementation of the public activate() and deactivate() + // methods above (assumes locks are held). + int deactivate_i (void); + // Deactivate the queue. + int activate_i (void); + // Activate the queue. + + ACE_Message_Block *head_; + // Pointer to head of ACE_Message_Block list. + + ACE_Message_Block *tail_; + // Pointer to tail of ACE_Message_Block list. + + int low_water_mark_; + // Lowest number before unblocking occurs. + + int high_water_mark_; + // Greatest number of bytes before blocking. + + int cur_bytes_; + // Current number of bytes in the queue. + + int cur_count_; + // Current number of messages in the queue. + + int deactivated_; + // Indicates that the queue is inactive. + + // = Synchronization primitives for controlling concurrent access. + ACE_SYNCH_MUTEX lock_; + // Protect queue from concurrent access. + + ACE_SYNCH_CONDITION notempty_cond_; + // Used to make threads sleep until the queue is no longer empty. + + ACE_SYNCH_CONDITION notfull_cond_; + // Used to make threads sleep until the queue is no longer full. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Message_Queue.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Message_Queue.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Message_Queue.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_MESSAGE_LIST_H */ diff --git a/ace/Message_Queue.i b/ace/Message_Queue.i new file mode 100644 index 00000000000..980fa487677 --- /dev/null +++ b/ace/Message_Queue.i @@ -0,0 +1,122 @@ +/* -*- C++ -*- */ +// $Id$ + +// Message_Queue.i + +#include "ace/Log_Msg.h" + +// Check if queue is empty (does not hold locks). + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Message_Queue<ACE_SYNCH_2>::is_empty_i (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::is_empty_i"); + return this->cur_bytes_ <= 0 && this->cur_count_ <= 0; +} + +// Check if queue is full (does not hold locks). + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Message_Queue<ACE_SYNCH_2>::is_full_i (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::is_full_i"); + return this->cur_bytes_ > this->high_water_mark_; +} + +// Check if queue is empty (holds locks). + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Message_Queue<ACE_SYNCH_2>::is_empty (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::is_empty"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + return this->is_empty_i (); +} + +// Check if queue is full (holds locks). + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Message_Queue<ACE_SYNCH_2>::is_full (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::is_full"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + return this->is_full_i (); +} + +template <ACE_SYNCH_1> ACE_INLINE size_t +ACE_Message_Queue<ACE_SYNCH_2>::high_water_mark (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::high_water_mark"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0); + + return this->high_water_mark_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Message_Queue<ACE_SYNCH_2>::high_water_mark (size_t hwm) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::high_water_mark"); + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_); + + this->high_water_mark_ = hwm; +} + +template <ACE_SYNCH_1> ACE_INLINE size_t +ACE_Message_Queue<ACE_SYNCH_2>::low_water_mark (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::low_water_mark"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0); + + return this->low_water_mark_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Message_Queue<ACE_SYNCH_2>::low_water_mark (size_t lwm) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::low_water_mark"); + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_); + + this->low_water_mark_ = lwm; +} + +// Return the current number of bytes in the queue. + +template <ACE_SYNCH_1> ACE_INLINE size_t +ACE_Message_Queue<ACE_SYNCH_2>::message_bytes (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::message_bytes"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0); + + return this->cur_bytes_; +} + +// Return the current number of messages in the queue. + +template <ACE_SYNCH_1> ACE_INLINE size_t +ACE_Message_Queue<ACE_SYNCH_2>::message_count (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::message_count"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0); + + return this->cur_count_; +} + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::activate (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::activate"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + return this->activate_i (); +} + +template <ACE_SYNCH_1> int +ACE_Message_Queue<ACE_SYNCH_2>::deactivate (void) +{ + ACE_TRACE ("ACE_Message_Queue<ACE_SYNCH_2>::deactivate"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + return this->deactivate_i (); +} diff --git a/ace/Method_Object.cpp b/ace/Method_Object.cpp new file mode 100644 index 00000000000..86fffea0812 --- /dev/null +++ b/ace/Method_Object.cpp @@ -0,0 +1,14 @@ +// Method_Object.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Method_Object.h" + +ACE_Method_Object::ACE_Method_Object (void) +{ +} + +ACE_Method_Object::~ACE_Method_Object (void) +{ +} + diff --git a/ace/Method_Object.h b/ace/Method_Object.h new file mode 100644 index 00000000000..49daaff39d5 --- /dev/null +++ b/ace/Method_Object.h @@ -0,0 +1,43 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Method_Object.h +// +// = AUTHOR +// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt +// <schmidt@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_METHOD_OBJECT_H) +#define ACE_METHOD_OBJECT_H + +#include "ace/OS.h" + +class ACE_Export ACE_Method_Object + // = TITLE + // Reifies a method into an object. Subclasses typically + // represent necessary state and behavior. + // + // = DESCRIPTION + // A <Method_Object> is inserted in the <Activation_Queue>, where + // it is subsequently removed by the <Scheduler> and invoked. +{ +public: + // = Initialization and termination methods. + ACE_Method_Object (void); + virtual ~ACE_Method_Object (void); + + // = Invocation method + virtual int call (void) = 0; + // Invoked when the <Method_Object> is scheduled to run. +}; + +#endif /* ACE_METHOD_OBJECT_H */ diff --git a/ace/Module.cpp b/ace/Module.cpp new file mode 100644 index 00000000000..46f6ae1ea76 --- /dev/null +++ b/ace/Module.cpp @@ -0,0 +1,168 @@ +// Module.cpp +// $Id$ + +#if !defined (ACE_MODULE_C) +#define ACE_MODULE_C + +#define ACE_BUILD_DLL +#include "ace/Module.h" +#include "ace/Stream_Modules.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Module.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Module) + +template <ACE_SYNCH_1> void +ACE_Module<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::dump"); +} + +template <ACE_SYNCH_1> void +ACE_Module<ACE_SYNCH_2>::writer (ACE_Task<ACE_SYNCH_2> *q) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::writer"); + this->q_pair_[1] = q; + if (q != 0) + ACE_CLR_BITS (q->flags_, ACE_Task_Flags::ACE_READER); +} + +template <ACE_SYNCH_1> void +ACE_Module<ACE_SYNCH_2>::reader (ACE_Task<ACE_SYNCH_2> *q) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::reader"); + this->q_pair_[0] = q; + if (q != 0) + ACE_SET_BITS (q->flags_, ACE_Task_Flags::ACE_READER); +} + +// Link this ACE_Module on top of ACE_Module M. + +template <ACE_SYNCH_1> void +ACE_Module<ACE_SYNCH_2>::link (ACE_Module<ACE_SYNCH_2> *m) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::link"); + this->next (m); + this->writer ()->next (m->writer ()); + m->reader ()->next (this->reader ()); +} + +template <ACE_SYNCH_1> int +ACE_Module<ACE_SYNCH_2>::open (char *mod_name, + ACE_Task<ACE_SYNCH_2> *writer_q, + ACE_Task<ACE_SYNCH_2> *reader_q, + void *arg) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::open"); + this->name (mod_name); + this->arg_ = arg; + + if (writer_q == 0) + writer_q = new ACE_Thru_Task<ACE_SYNCH_2>; + if (reader_q == 0) + reader_q = new ACE_Thru_Task<ACE_SYNCH_2>; + + // Make sure that the memory is allocated before proceding. + if (writer_q == 0 || reader_q == 0) + { + delete writer_q; + delete reader_q; + errno = ENOMEM; + return -1; + } + + this->reader (reader_q); + this->writer (writer_q); + + // Setup back pointers. + reader_q->mod_ = this; + writer_q->mod_ = this; + return 0; +} + +// Set and get pointer to sibling ACE_Task in ACE_Module. + +template <ACE_SYNCH_1> ACE_Task<ACE_SYNCH_2> * +ACE_Module<ACE_SYNCH_2>::sibling (ACE_Task<ACE_SYNCH_2> *orig) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::sibling"); + if (this->q_pair_[0] == orig) + return this->q_pair_[1]; + else if (this->q_pair_[1] == orig) + return this->q_pair_[0]; + else + return 0; +} + +template <ACE_SYNCH_1> ACE_INLINE +ACE_Module<ACE_SYNCH_2>::ACE_Module (void) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::ACE_Module"); + this->name ("<unknown>"); + // Do nothing... +} + +// Should never be called... +template <ACE_SYNCH_1> ACE_INLINE +ACE_Module<ACE_SYNCH_2>::~ACE_Module (void) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::~ACE_Module"); + ACE_ERROR ((LM_ERROR, "destructor for %s should never be called!\n", + this->name ())); +} + +template <ACE_SYNCH_1> ACE_INLINE +ACE_Module<ACE_SYNCH_2>::ACE_Module (char *mod_name, + ACE_Task<ACE_SYNCH_2> *writer_q, + ACE_Task<ACE_SYNCH_2> *reader_q, + void *flags) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::ACE_Module"); + if (this->open (mod_name, writer_q, reader_q, flags) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Module")); +} + +template <ACE_SYNCH_1> int +ACE_Module<ACE_SYNCH_2>::close (u_long flags) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::close"); + ACE_Task<ACE_SYNCH_2> *reader_q = this->reader (); + ACE_Task<ACE_SYNCH_2> *writer_q = this->writer (); + int result = 0; + + if (reader_q != 0) + { + if (reader_q->close () == -1) + result = -1; + reader_q->flush (); + reader_q->next (0); + } + + if (writer_q != 0) + { + if (writer_q->close () == -1) + result = -1; + writer_q->flush (); + writer_q->next (0); + } + + if (ACE_BIT_ENABLED (flags, ACE_Module<ACE_SYNCH_2>::M_DELETE)) + { + // Only delete the Tasks if there aren't any more threads + // running in them. + if (reader_q->thr_count () == 0) + delete reader_q; + this->reader (0); + + if (writer_q->thr_count () == 0) + delete writer_q; + this->writer (0); + + delete (void *) this; // Darn well better be allocated dynamically!!! + } + return result; +} + +#endif /* ACE_MODULE_C */ diff --git a/ace/Module.h b/ace/Module.h new file mode 100644 index 00000000000..b9983852a37 --- /dev/null +++ b/ace/Module.h @@ -0,0 +1,139 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Module.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_MODULE_H) +#define ACE_MODULE_H + +#include "ace/ACE.h" +#include "ace/Task.h" + +// Forward decl. +// template <ACE_SYNCH_1> class ACE_Task; + +template <ACE_SYNCH_1> +class ACE_Module + // = TITLE + // An abstraction for managing a bi-directional flow of messages. + // + // = DESCRIPTION + // This is based on the Module concept in System V Streams, + // which contains a pair of Tasks, one for handling upstream + // processing, one for handling downstream processing. +{ + friend class ACE_Shutup_GPlusPlus; // Turn off g++ warning +public: + enum + { + M_DELETE = 1 + // Indicates that close() deletes the Tasks. Don't change this + // value without updating the same enum in class ACE_Stream... + }; + + // = Initialization and termination methods. + ACE_Module (void); + // Create an empty Module. + + ACE_Module (char *module_name, + ACE_Task<ACE_SYNCH_2> *writer = 0, + ACE_Task<ACE_SYNCH_2> *reader = 0, void *a = 0); + // Create an initialized module with <module_name> as its identity + // and <reader> and <writer> as its tasks. + + int open (char *module_name, + ACE_Task<ACE_SYNCH_2> *writer = 0, + ACE_Task<ACE_SYNCH_2> *reader = 0, void *a = 0); + // Create an initialized module with <module_name> as its identity + // and <reader> and <writer> as its tasks. + + int close (u_long flags = M_DELETE); + // Close down the Module and its Tasks. If the <M_DELETE> argument + // is given then delete all the memory too. + + // = ACE_Task manipulation routines + ACE_Task<ACE_SYNCH_2> *writer (void); + // Get the writer task. + void writer (ACE_Task<ACE_SYNCH_2> *q); + // Set the writer task. + + ACE_Task<ACE_SYNCH_2> *reader (void); + // Get the reader task. + void reader (ACE_Task<ACE_SYNCH_2> *q); + // Set the reader task. + + ACE_Task<ACE_SYNCH_2> *sibling (ACE_Task<ACE_SYNCH_2> *orig); + // Set and get pointer to sibling ACE_Task in ACE_Module + + // = Identify the module + const char *name (void) const; + // Get the module name. + void name (char *); + // Set the module name. + + // = Argument to the Tasks. + void *arg (void) const; + // Get the argument passed to the tasks. + + void arg (void *); + // Set the argument passed to the tasks. + + void link (ACE_Module<ACE_SYNCH_2> *m); + // Link to other modules in the ustream stack + + ACE_Module<ACE_SYNCH_2> *next (void); + // Get the next pointer to the module above in the stream. + + void next (ACE_Module<ACE_SYNCH_2> *m); + // Set the next pointer to the module above in the stream. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ~ACE_Module (void); + // *Must* use dynamic allocation. + + ACE_Task<ACE_SYNCH_2> *q_pair_[2]; + // Pair of Tasks that form the "read-side" and "write-side" of the + // ACE_Module partitioning. + + char name_[MAXNAMLEN + 1]; + // Name of the ACE_Module. + + ACE_Module<ACE_SYNCH_2> *next_; + // Next ACE_Module in the stack. + + void *arg_; + // Argument passed through to the reader and writer task when they + // are opened. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Module.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Module.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Module.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_MODULE_H */ diff --git a/ace/Module.i b/ace/Module.i new file mode 100644 index 00000000000..affc11f568c --- /dev/null +++ b/ace/Module.i @@ -0,0 +1,62 @@ +/* -*- C++ -*- */ +// $Id$ + +// Module.i + +template <ACE_SYNCH_1> ACE_INLINE void * +ACE_Module<ACE_SYNCH_2>::arg (void) const +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::arg"); + return this->arg_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Module<ACE_SYNCH_2>::arg (void *a) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::arg"); + this->arg_ = a; +} + +template <ACE_SYNCH_1> ACE_INLINE const char * +ACE_Module<ACE_SYNCH_2>::name (void) const +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::name"); + return this->name_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Module<ACE_SYNCH_2>::name (char *n) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::name"); + ACE_OS::strncpy (this->name_, n, MAXNAMLEN); +} + +template <ACE_SYNCH_1> ACE_INLINE ACE_Task<ACE_SYNCH_2> * +ACE_Module<ACE_SYNCH_2>::writer (void) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::writer"); + return this->q_pair_[1]; +} + +template <ACE_SYNCH_1> ACE_INLINE ACE_Task<ACE_SYNCH_2> * +ACE_Module<ACE_SYNCH_2>::reader (void) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::reader"); + return this->q_pair_[0]; +} + +template <ACE_SYNCH_1> ACE_INLINE ACE_Module<ACE_SYNCH_2> * +ACE_Module<ACE_SYNCH_2>::next (void) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::next"); + return this->next_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Module<ACE_SYNCH_2>::next (ACE_Module<ACE_SYNCH_2> *m) +{ + ACE_TRACE ("ACE_Module<ACE_SYNCH_2>::next"); + this->next_ = m; +} + + diff --git a/ace/Multiplexor.cpp b/ace/Multiplexor.cpp new file mode 100644 index 00000000000..42b5eb753a6 --- /dev/null +++ b/ace/Multiplexor.cpp @@ -0,0 +1,13 @@ +// Multiplexor.cpp +// $Id$ + +#if defined (ACE_HAS_THREADS) + +#define ACE_BUILD_DLL +#include "ace/Multiplexor.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Multiplexor.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_THREADS */ diff --git a/ace/Multiplexor.h b/ace/Multiplexor.h new file mode 100644 index 00000000000..960d67e371e --- /dev/null +++ b/ace/Multiplexor.h @@ -0,0 +1,76 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Multiplexor.h +// +// Define the Driver and ACE_Multiplexor container classes. +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + + +#if !defined (ACE_MULTIPLEXOR_H) +#define ACE_MULTIPLEXOR_H + +#include "ace/Module.h" +#include "ace/Map_Manager.h" + +#if defined (ACE_HAS_THREADS) + +#if 0 +class Driver + // = TITLE + // + // + // = DESCRIPTION + // +{ +public: + Driver (void); + ~Driver (void); + + virtual int link_from_below (ACE_Module *mod); + virtual ACE_Module *alloc_module (Driver *) = 0; + virtual int unlink_from_below (ACE_Module *); +}; + +class ACE_Export ACE_Multiplexor + // = TITLE + // + // + // = DESCRIPTION + // +{ +public: + // = Constructors and destructors + ACE_Multiplexor (void); + ~ACE_Multiplexor (void); + + virtual int link_from_above (Driver &ld); + virtual int link_from_above (ACE_Multiplexor &lm); + virtual int link_from_below (ACE_Module *mod); + virtual ACE_Module *alloc_lower_module (ACE_Multiplexor *) = 0; + virtual ACE_Module *alloc_upper_module (ACE_Multiplexor *) = 0; + + virtual int unlink_from_above (Driver &ld); + virtual int unlink_from_above (ACE_Multiplexor &lm); + virtual int unlink_from_below (ACE_Module *mod); +}; + +#if defined (__ACE_INLINE__) +#include "ace/Multiplexor.i" +#endif /* __ACE_INLINE__ */ + +#endif /* 0 */ + +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_MULTIPLEXOR_H */ diff --git a/ace/Multiplexor.i b/ace/Multiplexor.i new file mode 100644 index 00000000000..1763c13ab4c --- /dev/null +++ b/ace/Multiplexor.i @@ -0,0 +1,88 @@ +/* -*- C++ -*- */ +// $Id$ + +// Multiplexor.i + +int +Driver::link_from_below (ACE_Module *stream_head) +{ + ACE_TRACE ("Driver::link_from_below"); + ACE_Module *stream_tail = this->alloc_module (this); + + stream_head->link (stream_tail); + if (stream_tail->reader ()->open () == -1 + || stream_tail->writer ()->open () == -1) + { + stream_tail->close (); + return -1; + } + return 0; +} + +int +Driver::unlink_from_below (ACE_Module *) +{ + ACE_TRACE ("Driver::unlink_from_below"); + return -1; +} + +ACE_Multiplexor::ACE_Multiplexor (void) +{ + ACE_TRACE ("ACE_Multiplexor::ACE_Multiplexor"); +} + +ACE_Multiplexor::~ACE_Multiplexor (void) +{ + ACE_TRACE ("ACE_Multiplexor::~ACE_Multiplexor"); +} + +int +ACE_Multiplexor::link_from_above (Driver &ld) +{ + ACE_TRACE ("ACE_Multiplexor::link_from_above"); + return ld.link_from_below (this->alloc_lower_module (this)); +} + +int +ACE_Multiplexor::link_from_above (ACE_Multiplexor &lm) +{ + ACE_TRACE ("ACE_Multiplexor::link_from_above"); + return lm.link_from_below (this->alloc_lower_module (this)); +} + +int +ACE_Multiplexor::link_from_below (ACE_Module *stream_head) +{ + ACE_TRACE ("ACE_Multiplexor::link_from_below"); + ACE_Module *stream_tail = this->alloc_upper_module (this); + + stream_head->link (stream_tail); + if (stream_tail->reader ()->open () == -1 + || stream_tail->writer ()->open () == -1) + { + stream_tail->close (); + return -1; + } + return 0; +} + +int +ACE_Multiplexor::unlink_from_above (Driver &) +{ + ACE_TRACE ("ACE_Multiplexor::unlink_from_above"); + return -1; +} + +int +ACE_Multiplexor::unlink_from_above (ACE_Multiplexor &) +{ + ACE_TRACE ("ACE_Multiplexor::unlink_from_above"); + return -1; +} + +int +ACE_Multiplexor::unlink_from_below (ACE_Module *) +{ + ACE_TRACE ("ACE_Multiplexor::unlink_from_below"); + return -1; +} diff --git a/ace/Name_Proxy.cpp b/ace/Name_Proxy.cpp new file mode 100644 index 00000000000..dadc2580b76 --- /dev/null +++ b/ace/Name_Proxy.cpp @@ -0,0 +1,175 @@ +// Name_Proxy.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Name_Proxy.h" + +void +ACE_Name_Proxy::dump (void) const +{ + ACE_TRACE ("ACE_Name_Proxy::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->connector_.dump (); + this->peer_.dump (); + ACE_DEBUG ((LM_DEBUG, "reactor_ = %x", this->reactor_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Default constructor. + +ACE_Name_Proxy::ACE_Name_Proxy (void) + : reactor_ (0) +{ + ACE_TRACE ("ACE_Name_Proxy::ACE_Name_Proxy"); +} + +// Establish binding with the ACE_Name Server at remote_addr. + +int +ACE_Name_Proxy::open (const ACE_INET_Addr &remote_addr, + ACE_Synch_Options& options) +{ + ACE_TRACE ("ACE_Name_Proxy::open"); + ACE_Time_Value *timeout = 0; + + if (options[ACE_Synch_Options::USE_TIMEOUT]) + timeout = (ACE_Time_Value *) &ACE_Time_Value::zero; + else + timeout = (ACE_Time_Value *) options.time_value (); + + // Initiate the connection. + return this->connector_.connect (this->peer_, remote_addr, timeout); +} + +// Establish binding with the ACE_Name Server at remote_addr. + +ACE_Name_Proxy::ACE_Name_Proxy (const ACE_INET_Addr &remote_addr, + ACE_Synch_Options& options) +{ + ACE_TRACE ("ACE_Name_Proxy::ACE_Name_Proxy"); + if (this->open (remote_addr, options) == -1 + && options[ACE_Synch_Options::USE_TIMEOUT] && errno != EWOULDBLOCK) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Name_Proxy::ACE_Name_Proxy")); +} + +// Obtain underlying handle. + +/* VIRTUAL */ ACE_HANDLE +ACE_Name_Proxy::get_handle (void) const +{ + ACE_TRACE ("ACE_Name_Proxy::get_handle"); + return this->peer_.get_handle (); +} + +int +ACE_Name_Proxy::request_reply (ACE_Name_Request &request) +{ + ACE_TRACE ("ACE_Name_Proxy::request_reply"); + void *buffer; + ssize_t length; + + if ((length = request.encode (buffer)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "encode failed"), -1); + + // Transmit request via a blocking send. + + if (this->peer_.send_n (buffer, length) != length) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send_n failed"), -1); + else + { + ACE_Name_Reply reply; + + // Receive reply via blocking read. + + if (this->peer_.recv (&reply, sizeof reply) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "recv failed"), -1); + + else if (reply.decode () == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "decode failed"), -1); + + errno = int (reply.errnum ()); + return reply.status (); + } +} + +int +ACE_Name_Proxy::send_request (ACE_Name_Request &request) +{ + ACE_TRACE ("ACE_Name_Proxy::send_request"); + void *buffer; + ssize_t length; + + if ((length = request.encode (buffer)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "encode failed"), -1); + + // Transmit request via a blocking send. + + else if (this->peer_.send_n (buffer, length) != length) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send_n failed"), -1); + + return 0; +} + +int +ACE_Name_Proxy::recv_reply (ACE_Name_Request &reply) +{ + ACE_TRACE ("ACE_Name_Proxy::recv_reply"); + // Read the first 4 bytes to get the length of the message + // This implementation assumes that the first 4 bytes are + // the length of the message. + ssize_t n = this->peer_.recv ((void *) &reply, sizeof (ACE_UINT32)); + + switch (n) + { + case -1: + // FALLTHROUGH + ACE_DEBUG ((LM_DEBUG, "****************** recv_reply returned -1\n")); + default: + ACE_ERROR ((LM_ERROR, "%p got %d bytes, expected %d bytes\n", + "recv failed", n, sizeof (ACE_UINT32))); + // FALLTHROUGH + case 0: + // We've shutdown unexpectedly + return -1; + // NOTREACHED + case sizeof (ACE_UINT32): + { + // Transform the length into host byte order. + ssize_t length = ntohl (reply.length ()); + + // Receive the rest of the request message. + // @@ beware of blocking read!!!. + n = this->peer_.recv ((void *) (((char *) &reply) + + sizeof (ACE_UINT32)), + length - sizeof (ACE_UINT32)); + + // Subtract off the size of the part we skipped over... + if (n != ssize_t (length - sizeof (ACE_UINT32))) + { + ACE_ERROR ((LM_ERROR, "%p expected %d, got %d\n", + "invalid length", length, n)); + return -1; + } + + // Decode the request into host byte order. + if (reply.decode () == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "decode failed")); + return -1; + } + } + } + return 0; +} + +// Close down the connection to the server. + +ACE_Name_Proxy::~ACE_Name_Proxy (void) +{ + ACE_TRACE ("ACE_Name_Proxy::~ACE_Name_Proxy"); + this->peer_.close (); +} + + diff --git a/ace/Name_Proxy.h b/ace/Name_Proxy.h new file mode 100644 index 00000000000..f99fff09d9d --- /dev/null +++ b/ace/Name_Proxy.h @@ -0,0 +1,82 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Name_Proxy.h +// +// = DESCRIPTION +// Proxy for dealing with remote server process managing NET_LOCAL +// Name_Bindings. +// +// = AUTHOR +// Gerhard Lenzer, Douglas C. Schmidt, and Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_NAME_PROXY_H) +#define ACE_NAME_PROXY_H + +#include "ace/INET_Addr.h" +#include "ace/SOCK_Connector.h" +#include "ace/SOCK_Stream.h" +#include "ace/Service_Config.h" +#include "ace/Synch_Options.h" +#include "ace/Name_Request_Reply.h" + +class ACE_Export ACE_Name_Proxy : public ACE_Event_Handler + // = TITLE + // Proxy for dealing with remote server process managing NET_LOCAL NameBindings + // + // = DESCRIPTION + // Shields applications from details of interacting with the ACE_Name Server. +{ +public: + ACE_Name_Proxy (void); + // Default constructor. + + // = Establish a binding with the ACE_Name Server. + ACE_Name_Proxy (const ACE_INET_Addr &remote_addr, // Address of ACE_Name Server. + ACE_Synch_Options& options = + ACE_Synch_Options::defaults); + + int open (const ACE_INET_Addr &remote_addr, // Address of ACE_Name Server. + ACE_Synch_Options& options = + ACE_Synch_Options::defaults); + + int request_reply (ACE_Name_Request &request); + // Perform the request and wait for the reply. + + int send_request (ACE_Name_Request &request); + // Perform the request. + + int recv_reply (ACE_Name_Request &reply); + // Receive the reply. + + virtual ACE_HANDLE get_handle (void) const; + // Obtain underlying handle. + + virtual ~ACE_Name_Proxy (void); + // Close down the connection to the server. + + void dump (void) const; + // Dump the state of the object; + +private: + + ACE_SOCK_Connector connector_; + // ACE_Connector factory used to establish connections actively. + + ACE_SOCK_Stream peer_; + // Connection to ACE_Name Server peer. + + ACE_Reactor *reactor_; + // Pointer to ACE_Reactor (used if we are run in "reactive-mode"). +}; + +#endif /* ACE_NAME_PROXY_H */ diff --git a/ace/Name_Request_Reply.cpp b/ace/Name_Request_Reply.cpp new file mode 100644 index 00000000000..804ae6ce89d --- /dev/null +++ b/ace/Name_Request_Reply.cpp @@ -0,0 +1,491 @@ +// Name_Request_Reply.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Name_Request_Reply.h" + +// Default "do nothing" constructor. + +ACE_Name_Request::ACE_Name_Request (void) +{ + ACE_TRACE ("ACE_Name_Request::ACE_Name_Request"); +} + +// Create a ACE_Name_Request message. + +ACE_Name_Request::ACE_Name_Request (ACE_UINT32 t, // Type of request. + const ACE_USHORT16 name[], // Name + const size_t name_length, // size in bytes + const ACE_USHORT16 value[], // + const size_t value_length, // size in bytes + const char type[], // + const size_t type_length, // size in bytes + ACE_Time_Value *timeout) // Max time waiting for request. +{ + ACE_TRACE ("ACE_Name_Request::ACE_Name_Request"); + this->msg_type (t); + this->name_len (name_length); + this->value_len (value_length); + this->type_len (type_length); + + // If timeout is a NULL pointer, then block forever... + if (timeout == 0) + { + this->transfer_.block_forever_ = 1; + this->transfer_.sec_timeout_ = 0; + this->transfer_.usec_timeout_ = 0; + } + else // Do a "timed wait." + { + this->block_forever (0); + // Keep track of how long client is willing to wait. + this->transfer_.sec_timeout_ = timeout->sec (); + this->transfer_.usec_timeout_ = timeout->usec (); + } + + // Set up pointers and copy name value and type into request. + this->name_ = this->transfer_.data_; + this->value_ = &this->name_[name_length / sizeof (ACE_USHORT16) ]; + this->type_ = (char *)(&this->value_[value_length / sizeof (ACE_USHORT16)]); // + + (void) ACE_OS::memcpy (this->name_, name, name_length); + (void) ACE_OS::memcpy (this->value_, value, value_length); + (void) ACE_OS::memcpy (this->type_, type, type_length); + + // Compute size of the fixed portion of the message... + size_t len = sizeof this->transfer_ - sizeof this->transfer_.data_; + + // ... then add in the amount of the variable-sized portion. + len += name_length + value_length + type_length ; + + this->length (len); +} + +// Initialize length_ in order to avoid problems with byte-ordering +void +ACE_Name_Request::init (void) +{ + ACE_TRACE ("ACE_Name_Request::init"); + this->length (sizeof this->transfer_); +} + +// = Set/get the length of the encoded/decoded message. +ACE_UINT32 +ACE_Name_Request::length (void) const +{ + ACE_TRACE ("ACE_Name_Request::length"); + return this->transfer_.length_; +} + +void +ACE_Name_Request::length (ACE_UINT32 l) +{ + ACE_TRACE ("ACE_Name_Request::length"); + this->transfer_.length_ = l; +} + +// = Set/get the type of the message. +ACE_UINT32 +ACE_Name_Request::msg_type (void) const +{ + ACE_TRACE ("ACE_Name_Request::msg_type"); + return this->transfer_.msg_type_; +} + +void +ACE_Name_Request::msg_type (ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Name_Request::msg_type"); + this->transfer_.msg_type_ = t; +} + +// = Set/get the len of the name +ACE_UINT32 +ACE_Name_Request::name_len (void) const +{ + ACE_TRACE ("ACE_Name_Request::name_len"); + return this->transfer_.name_len_; +} + +void +ACE_Name_Request::name_len (ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Name_Request::name_len"); + this->transfer_.name_len_ = t; +} + +// = Set/get the len of the value +ACE_UINT32 +ACE_Name_Request::value_len (void) const +{ + ACE_TRACE ("ACE_Name_Request::value_len"); + return this->transfer_.value_len_; +} + +void +ACE_Name_Request::value_len (ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Name_Request::value_len"); + this->transfer_.value_len_ = t; +} + +// = Set/get the len of the type +ACE_UINT32 +ACE_Name_Request::type_len (void) const +{ + ACE_TRACE ("ACE_Name_Request::type_len"); + return this->transfer_.type_len_; +} + +void +ACE_Name_Request::type_len (ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Name_Request::type_len"); + this->transfer_.type_len_ = t; +} + +// = Set/get the blocking semantics. +ACE_UINT32 +ACE_Name_Request::block_forever (void) const +{ + ACE_TRACE ("ACE_Name_Request::block_forever"); + return this->transfer_.block_forever_; +} + +void +ACE_Name_Request::block_forever (ACE_UINT32 bs) +{ + ACE_TRACE ("ACE_Name_Request::block_forever"); + this->transfer_.block_forever_ = bs; +} + +// = Set/get the timeout. +ACE_Time_Value +ACE_Name_Request::timeout (void) const +{ + ACE_TRACE ("ACE_Name_Request::timeout"); + return ACE_Time_Value (this->transfer_.sec_timeout_, this->transfer_.usec_timeout_); +} + +void +ACE_Name_Request::timeout (const ACE_Time_Value timeout) +{ + ACE_TRACE ("ACE_Name_Request::timeout"); + this->transfer_.sec_timeout_ = timeout.sec (); + this->transfer_.usec_timeout_ = timeout.usec (); +} + +// = Set/get the name +const ACE_USHORT16 * +ACE_Name_Request::name (void) const +{ + ACE_TRACE ("ACE_Name_Request::name"); + return this->name_; +} + +void +ACE_Name_Request::name (const ACE_USHORT16 *t) +{ + ACE_TRACE ("ACE_Name_Request::name"); + (void) ACE_OS::memcpy (this->name_, t, this->name_len()); +} + +// = Set/get the value +const ACE_USHORT16 * +ACE_Name_Request::value (void) const +{ + ACE_TRACE ("ACE_Name_Request::value"); + return this->value_; +} + +void +ACE_Name_Request::value (const ACE_USHORT16 *c) +{ + ACE_TRACE ("ACE_Name_Request::value"); + (void) ACE_OS::memcpy (this->value_, c, this->value_len()); +} + +// = Set/get the type +const char * +ACE_Name_Request::type (void) const +{ + ACE_TRACE ("ACE_Name_Request::type"); + return this->type_; +} + +void +ACE_Name_Request::type (const char *c) +{ + ACE_TRACE ("ACE_Name_Request::type"); + (void) ::strncpy (this->type_, c, MAXPATHLEN + 1); +} + +// Encode the transfer buffer into network byte order +// so that it can be sent to the server. + +int +ACE_Name_Request::encode (void *&buf) +{ + ACE_TRACE ("ACE_Name_Request::encode"); + // Compute the length *before* doing the marshaling. + ssize_t len = this->length (); + size_t nv_data_len = + (this->transfer_.name_len_ + this->transfer_.value_len_) / sizeof (ACE_USHORT16); + + for (size_t i = 0; i < nv_data_len; i++) + this->transfer_.data_[i] = htons (this->transfer_.data_[i]); + + buf = (void *) &this->transfer_; + this->transfer_.block_forever_ = htonl (this->transfer_.block_forever_); + this->transfer_.usec_timeout_ = htonl (this->transfer_.usec_timeout_); + this->transfer_.sec_timeout_ = htonl (this->transfer_.sec_timeout_); + this->transfer_.length_ = htonl (this->transfer_.length_); + this->transfer_.msg_type_ = htonl (this->transfer_.msg_type_); + this->transfer_.name_len_ = htonl (this->transfer_.name_len_); + this->transfer_.value_len_ = htonl (this->transfer_.value_len_); + this->transfer_.type_len_ = htonl (this->transfer_.type_len_); + + return len; +} + +// Decode the transfer buffer into host byte byte order +// so that it can be used by the server. + +int +ACE_Name_Request::decode (void) +{ + ACE_TRACE ("ACE_Name_Request::decode"); + // Decode the fixed-sized portion first. + this->transfer_.block_forever_ = ntohl (this->transfer_.block_forever_); + this->transfer_.usec_timeout_ = ntohl (this->transfer_.usec_timeout_); + this->transfer_.sec_timeout_ = ntohl (this->transfer_.sec_timeout_); + this->transfer_.length_ = ntohl (this->transfer_.length_); + this->transfer_.msg_type_ = ntohl (this->transfer_.msg_type_); + this->transfer_.name_len_ = ntohl (this->transfer_.name_len_); + this->transfer_.value_len_ = ntohl (this->transfer_.value_len_); + this->transfer_.type_len_ = ntohl (this->transfer_.type_len_); + + size_t nv_data_len = + (this->transfer_.name_len_ + this->transfer_.value_len_) / sizeof (ACE_USHORT16); + + for (size_t i = 0; i < nv_data_len; i++) + this->transfer_.data_[i] = ntohs (this->transfer_.data_[i]); + + this->name_ = this->transfer_.data_; + this->value_ = &this->name_[this->transfer_.name_len_ / sizeof (ACE_USHORT16)]; + this->type_ = (char *)(&this->value_[this->transfer_.value_len_ / sizeof (ACE_USHORT16)]); + this->type_[this->transfer_.type_len_] = '\0'; + + // Decode the variable-sized portion. + return 0; +} + +// Print out the current values of the ACE_Name_Request. + +void +ACE_Name_Request::dump (void) const +{ + ACE_TRACE ("ACE_Name_Request::dump"); + ACE_DEBUG ((LM_DEBUG, "*******\nlength = %d\n", + this->length ())); + ACE_DEBUG ((LM_DEBUG, "message-type = ")); + + switch (this->msg_type ()) + { + case ACE_Name_Request::BIND: + ACE_DEBUG ((LM_DEBUG, "BIND\n")); + break; + case ACE_Name_Request::REBIND: + ACE_DEBUG ((LM_DEBUG, "REBIND\n")); + break; + case ACE_Name_Request::RESOLVE: + ACE_DEBUG ((LM_DEBUG, "RESOLVE\n")); + break; + case ACE_Name_Request::UNBIND: + ACE_DEBUG ((LM_DEBUG, "UNBIND\n")); + break; + case ACE_Name_Request::LIST_NAMES: + ACE_DEBUG ((LM_DEBUG, "LIST_NAMES\n")); + break; + case ACE_Name_Request::LIST_VALUES: + ACE_DEBUG ((LM_DEBUG, "LIST_VALUES\n")); + break; + case ACE_Name_Request::LIST_TYPES: + ACE_DEBUG ((LM_DEBUG, "LIST_TYPES\n")); + break; + case ACE_Name_Request::LIST_NAME_ENTRIES: + ACE_DEBUG ((LM_DEBUG, "LIST_NAME_ENTRIES\n")); + break; + case ACE_Name_Request::LIST_VALUE_ENTRIES: + ACE_DEBUG ((LM_DEBUG, "LIST_VALUE_ENTRIES\n")); + break; + case ACE_Name_Request::LIST_TYPE_ENTRIES: + ACE_DEBUG ((LM_DEBUG, "LIST_TYPE_ENTRIES\n")); + break; + default: + ACE_DEBUG ((LM_DEBUG, "<unknown type> = %d\n", this->msg_type ())); + break; + } + + if (this->block_forever ()) + ACE_DEBUG ((LM_DEBUG, "blocking forever\n")); + else + { + ACE_Time_Value tv = this->timeout (); + ACE_DEBUG ((LM_DEBUG, "waiting for %ld secs and %ld usecs\n", + tv.sec (), tv.usec ())); + } + ACE_DEBUG ((LM_DEBUG, "*******\nname_len = %d\n", + this->name_len ())); + ACE_DEBUG ((LM_DEBUG, "*******\nvalue_len = %d\n", + this->value_len ())); +#if 0 + cout << "Name = " << ACE_WString (this->name(), this->name_len() / sizeof (ACE_USHORT16)) << endl; + cout << "value = " << ACE_WString (this->value(), this->value_len() / sizeof (ACE_USHORT16)) << endl; + cout << "type = " << this->type () << endl; +#endif + ACE_DEBUG ((LM_DEBUG, "+++++++\n")); +} + +// Default constructor. + +ACE_Name_Reply::ACE_Name_Reply (void) +{ + ACE_TRACE ("ACE_Name_Reply::ACE_Name_Reply"); + // Initialize to a known quantity. + this->msg_type (0); + this->errnum (0); + this->length (sizeof this->transfer_); +} + +// Create a ACE_Name_Reply message. + +ACE_Name_Reply::ACE_Name_Reply (ACE_UINT32 t, ACE_UINT32 err) // Type of reply. +{ + ACE_TRACE ("ACE_Name_Reply::ACE_Name_Reply"); + this->msg_type (t); + this->errnum (err); + this->length (sizeof this->transfer_); +} + +// Initialize length_ in order to avoid problems with byte-ordering +void +ACE_Name_Reply::init (void) +{ + ACE_TRACE ("ACE_Name_Reply::init"); + this->length (sizeof this->transfer_); +} + +// = Set/get the length of the encoded/decoded message. +ACE_UINT32 +ACE_Name_Reply::length (void) const +{ + ACE_TRACE ("ACE_Name_Reply::length"); + return this->transfer_.length_; +} + +void +ACE_Name_Reply::length (ACE_UINT32 l) +{ + ACE_TRACE ("ACE_Name_Reply::length"); + this->transfer_.length_ = l; +} + +// = Set/get the type of the message. +ACE_UINT32 +ACE_Name_Reply::msg_type (void) const +{ + ACE_TRACE ("ACE_Name_Reply::msg_type"); + return this->transfer_.type_; +} + +void +ACE_Name_Reply::msg_type (ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Name_Reply::msg_type"); + this->transfer_.type_ = t; +} + +// = Set/get the status of the reply (0 == success, -1 == failure). +ACE_UINT32 +ACE_Name_Reply::status (void) const +{ + ACE_TRACE ("ACE_Name_Reply::status"); + return this->transfer_.type_ == ACE_Name_Reply::SUCCESS ? 0 : -1; +} + +void +ACE_Name_Reply::status (ACE_UINT32 s) +{ + ACE_TRACE ("ACE_Name_Reply::status"); + this->transfer_.type_ = s == (ACE_UINT32) -1 ? ACE_Name_Reply::FAILURE : ACE_Name_Reply::SUCCESS; +} + +// = Set/get the errno of a failed reply. +ACE_UINT32 +ACE_Name_Reply::errnum (void) const +{ + ACE_TRACE ("ACE_Name_Reply::errnum"); + return this->transfer_.errno_; +} + +void +ACE_Name_Reply::errnum (ACE_UINT32 e) +{ + ACE_TRACE ("ACE_Name_Reply::errnum"); + this->transfer_.errno_ = e; +} + +// Encode the transfer buffer into network byte order +// so that it can be sent to the client. + +int +ACE_Name_Reply::encode (void *&buf) +{ + ACE_TRACE ("ACE_Name_Reply::encode"); + int len = this->length (); // Get length *before* marshaling. + + this->transfer_.length_ = htonl (this->transfer_.length_); + this->transfer_.type_ = htonl (this->transfer_.type_); + this->transfer_.errno_ = htonl (this->transfer_.errno_); + buf = (void *) &this->transfer_; + return len; +} + +// Decode the transfer buffer into host byte order +// so that it can be used by the client. + +int +ACE_Name_Reply::decode (void) +{ + ACE_TRACE ("ACE_Name_Reply::decode"); + this->transfer_.length_ = ntohl (this->transfer_.length_); + this->transfer_.type_ = ntohl (this->transfer_.type_); + this->transfer_.errno_ = ntohl (this->transfer_.errno_); + return 0; +} + +// Print out current values of the ACE_Name_Reply object. + +void +ACE_Name_Reply::dump (void) const +{ + ACE_TRACE ("ACE_Name_Reply::dump"); + ACE_DEBUG ((LM_DEBUG, "*******\nlength = %d\nerrnum = %d", + this->length (), this->errnum ())); + ACE_DEBUG ((LM_DEBUG, "type = ")); + + switch (this->msg_type ()) + { + case ACE_Name_Reply::SUCCESS: + ACE_DEBUG ((LM_DEBUG, "SUCCESS\n")); + break; + case ACE_Name_Reply::FAILURE: + ACE_DEBUG ((LM_DEBUG, "FAILURE\n")); + break; + default: + ACE_DEBUG ((LM_DEBUG, "<unknown type> = %d\n", this->msg_type ())); + break; + } +} diff --git a/ace/Name_Request_Reply.h b/ace/Name_Request_Reply.h new file mode 100644 index 00000000000..dfc9cb5deed --- /dev/null +++ b/ace/Name_Request_Reply.h @@ -0,0 +1,253 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Name_Request_Reply.h +// +// = DESCRIPTION +// Define the format used to exchange messages between the +// ACE_Name Server and its clients. +// +// = AUTHOR +// Gerhard Lenzer, Douglas C. Schmidt, and Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_NAME_REQUEST_REPLY_H) +#define ACE_NAME_REQUEST_REPLY_H + +#include "ace/Time_Value.h" +#include "ace/SString.h" + +class ACE_Export ACE_Name_Request + // = TITLE + // Message format for delivering requests to the ACE_Name Server. + // + // = DESCRIPTION + // This class is implemented to minimize data copying. + // In particular, all marshaling is done in situ... +{ +public: + enum Constants + { + /* Request message types. */ + BIND = 01, + REBIND = 02, + RESOLVE = 03, + UNBIND = 04, + LIST_NAMES = 05, + LIST_VALUES = 015, + LIST_TYPES = 025, + LIST_NAME_ENTRIES = 06, + LIST_VALUE_ENTRIES = 016, + LIST_TYPE_ENTRIES = 026, + MAX_ENUM = 11, + MAX_LIST = 3, + + // Mask for bitwise operation used for table lookup + OP_TABLE_MASK = 07, // Mask for lookup of operation + LIST_OP_MASK = 030, // Mask for lookup of list_operation + + /* Class-specific constant values. */ + MAX_NAME_LEN = MAXPATHLEN + 1 + }; + + ACE_Name_Request (void); + // Default constructor. + + ACE_Name_Request (ACE_UINT32 msg_type, // Type of request. + const ACE_USHORT16 name[], // + const size_t name_length, + const ACE_USHORT16 value[], + const size_t value_length, + const char type[], + const size_t type_length, + ACE_Time_Value *timeout = 0); // Max time willing to wait for request. + // Create a <ACE_Name_Request> message. + + void init (void); + // Initialize length_ in order to ensure correct byte ordering + // before a request is sent. + + // = Set/get the length of the encoded/decoded message. + ACE_UINT32 length (void) const; + void length (ACE_UINT32); + + // = Set/get the type of the message. + ACE_UINT32 msg_type (void) const; + void msg_type (ACE_UINT32); + + // = Set/get the blocking semantics. + ACE_UINT32 block_forever (void) const; + void block_forever (ACE_UINT32); + + // = Set/get the timeout. + ACE_Time_Value timeout (void) const; + void timeout (const ACE_Time_Value timeout); + + // = Set/get the name + const ACE_USHORT16 *name (void) const; + void name (const ACE_USHORT16 *); + + // = Set/get the value + const ACE_USHORT16 *value (void) const; + void value (const ACE_USHORT16 *); + + // = Set/get the type + const char *type (void) const; + void type (const char *); + + // = Set/get the len of name + ACE_UINT32 name_len (void) const; + void name_len (ACE_UINT32); + + // = Set/get the len of value + ACE_UINT32 value_len (void) const; + void value_len (ACE_UINT32); + + // = Set/get the len of type + ACE_UINT32 type_len (void) const; + void type_len (ACE_UINT32); + + int encode (void *&); + // Encode the message before transmission. + + int decode (void); + // Decode message after reception. + + void dump (void) const; + // Print out the values of the message for debugging purposes. + +private: + // = The 5 fields in the <Transfer> struct are transmitted to the server. + // The remaining 2 fields are not tranferred -- they are used only on + // the server-side to simplify lookups. + + struct Transfer + { + ACE_UINT32 length_; + // Length of entire request. + + ACE_UINT32 msg_type_; + // Type of the request (i.e., <BIND>, <REBIND>, <RESOLVE>, and <UNBIND>). + + ACE_UINT32 block_forever_; + // Indicates if we should block forever. If 0, then <secTimeout_> + // and <usecTimeout_> indicates how long we should wait. + + ACE_UINT32 sec_timeout_; + // Max seconds willing to wait for name if not blocking forever. + + ACE_UINT32 usec_timeout_; + // Max micro seconds to wait for name if not blocking forever. + + ACE_UINT32 name_len_; + // Len of name in bytes + + ACE_UINT32 value_len_; + // Len of value in bytes + + ACE_UINT32 type_len_; + // Len of type in bytes + + ACE_USHORT16 data_[MAX_NAME_LEN + MAXPATHLEN + MAXPATHLEN + 2]; + // The data portion contains the <name_> + // followed by the <value_> + // followed by the <type_>. + }; + + Transfer transfer_; + // Transfer buffer. + + ACE_USHORT16 *name_; + // Pointer to the beginning of the name in this->data_. + + ACE_USHORT16 *value_; + // Pointer to the beginning of the value in this->data_; + + char *type_; + // Pointer to the beginning of the type in this->data_; +}; + +class ACE_Export ACE_Name_Reply + // = TITLE + // Message format for delivering replies from the ACE_Name Server. + // + // = DESCRIPTION + // This class is implemented to minimize data copying. + // In particular, all marshaling is done in situ... +{ +public: + enum Constants + { + /* Reply message types. */ + SUCCESS = 1, // Reply for successful operation. + FAILURE = 2, // Reply for failed operation. + + /* Class-specific constant values. */ + MAX_NAME_LEN = MAXPATHLEN + 1 + }; + + ACE_Name_Reply (void); + // Default constructor. + + ACE_Name_Reply (ACE_UINT32 type, ACE_UINT32 err); // Type of reply. + // Create a <ACE_Name_Reply> message. + + void init (void); + // Initialize length_ in order to ensure correct byte ordering + // before a reply is sent. + + // = Set/get the length of the encoded/decoded message. + ACE_UINT32 length (void) const; + void length (ACE_UINT32); + + // = Set/get the type of the message. + ACE_UINT32 msg_type (void) const; + void msg_type (ACE_UINT32); + + // = Set/get the status of the reply (0 == success, -1 == failure). + ACE_UINT32 status (void) const; + void status (ACE_UINT32); + + // = Set/get the errno of a failed reply. + ACE_UINT32 errnum (void) const; + void errnum (ACE_UINT32); + + int encode (void *&); + // Encode the message before transfer. + + int decode (void); + // Decode a message after reception. + + void dump (void) const; + // Print out the values of the message for debugging purposes. + +private: + // = The 3 fields in the <Transfer> struct are transmitted to the server. + + struct Transfer + { + ACE_UINT32 length_; + // Length of entire reply. + + ACE_UINT32 type_; + // Type of the reply (i.e., <SUCCESS> or <FAILURE>). + + ACE_UINT32 errno_; + // Indicates why error occurred if <this->type_> == <FAILURE>. + // Typical reasons include: + // <ETIME> (if the client timed out after waiting for the name). + }; + + Transfer transfer_; + // Transfer buffer. +}; + +#endif /* ACE_NAME_REQUEST_REPLY_H */ diff --git a/ace/Name_Space.cpp b/ace/Name_Space.cpp new file mode 100644 index 00000000000..e684003509b --- /dev/null +++ b/ace/Name_Space.cpp @@ -0,0 +1,60 @@ +// Name_Space.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Name_Space.h" + +ACE_Name_Binding::ACE_Name_Binding (void) + : type_ (ACE_OS::strdup ("")) +{ + ACE_TRACE ("ACE_Name_Binding::ACE_Name_Binding"); +} + + +ACE_Name_Binding::~ACE_Name_Binding (void) +{ + ACE_TRACE ("ACE_Name_Binding::~ACE_Name_Binding"); + ACE_OS::free ((void *) this->type_); +} + +ACE_Name_Binding::ACE_Name_Binding (const ACE_WString &name, + const ACE_WString &value, + const char *type) + : name_ (name), + value_ (value), + type_ (type == 0 ? ACE_OS::strdup ("") : ACE_OS::strdup (type)) +{ + ACE_TRACE ("ACE_Name_Binding::ACE_Name_Binding"); +} + +ACE_Name_Binding::ACE_Name_Binding (const ACE_Name_Binding &s) + : name_ (s.name_), + value_ (s.value_), + type_ (ACE_OS::strdup (s.type_)) +{ + ACE_TRACE ("ACE_Name_Binding::ACE_Name_Binding"); +} + +void +ACE_Name_Binding::operator = (const ACE_Name_Binding &s) +{ + ACE_TRACE ("ACE_Name_Binding::operator ="); + + this->name_ = s.name_; + this->value_ = s.value_; + this->type_ = ACE_OS::strdup (s.type_); +} + +int +ACE_Name_Binding::operator == (const ACE_Name_Binding &s) const +{ + ACE_TRACE ("ACE_Name_Binding::operator =="); + return this->name_ == s.name_ + && this->value_ == s.value_ + && ACE_OS::strcmp (this->type_, s.type_) == 0; +} + +ACE_Name_Space::~ACE_Name_Space (void) +{ + ACE_TRACE ("ACE_Name_Space::~ACE_Name_Space"); +} diff --git a/ace/Name_Space.h b/ace/Name_Space.h new file mode 100644 index 00000000000..78a274e86b5 --- /dev/null +++ b/ace/Name_Space.h @@ -0,0 +1,145 @@ +/* -*- C++ -*- */ +// $Id$ + +/*-*- C++ -*- */ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Name_Space +// +// = AUTHOR +// Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_NAME_SPACE_H) +#define ACE_NAME_SPACE_H + +#include "ace/ACE.h" +#include "ace/SString.h" +#include "ace/Set.h" +#include "ace/Name_Proxy.h" + +typedef ACE_Unbounded_Set<ACE_WString> ACE_WSTRING_SET; + +class ACE_Export ACE_Name_Binding +{ +public: + // = Initialization and termination. + ACE_Name_Binding (const ACE_WString &n, + const ACE_WString &v, + const char *t); + // Main constructor that initializes all the fields. + + ACE_Name_Binding (void); + // Default constructor. + + ACE_Name_Binding (const ACE_Name_Binding &); + // Copy constructor. + + void operator= (const ACE_Name_Binding &); + // Assignment operator. + + ~ACE_Name_Binding (void); + // Destructor. + + int operator == (const ACE_Name_Binding &s) const; + // Test for equality. + + ACE_WString name_; + // Name of the binding. + + ACE_WString value_; + // Value of the binding. + + char *type_; + // Type of the binding. +}; + +typedef ACE_Unbounded_Set<ACE_Name_Binding> ACE_BINDING_SET; +typedef ACE_Unbounded_Set_Iterator<ACE_Name_Binding> ACE_BINDING_ITERATOR; + +typedef ACE_Unbounded_Set<ACE_WString> ACE_PWSTRING_SET; +typedef ACE_Unbounded_Set_Iterator<ACE_WString> ACE_PWSTRING_ITERATOR; + +class ACE_Export ACE_Name_Space + // = TITLE + // Abstract base class that provides an abstract interface to + // the database without exposing any implemenation details. + // + // = DESCRIPTION + // Manages a Naming Service Name Space. Provides the basic + // methods -- bind, unbind, rebind, find, and listnames. +{ +public: + + virtual ~ACE_Name_Space (void); + // virtual destructor to ensure destructors of subclasses get + // called. + + virtual int bind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in = "") = 0; + // Bind a new name to a naming context (Wide character strings). + + + virtual int rebind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in = "") = 0; + // Overwrite the value or type of an existing name in a + // ACE_Name_Space or bind a new name to the context, if it didn't + // exist yet. (Wide charcter strings interface). + + virtual int unbind (const ACE_WString &name_in) = 0; + // Delete a name from a ACE_Name_Space (Wide charcter strings + // Interface). + + virtual int resolve (const ACE_WString &name_in, + ACE_WString &value_out, + char *&type_out) = 0; + // Get value and type of a given name binding (Wide chars). The + // caller is responsible for deleting both <value_out> and <type_out>! + + virtual int list_names (ACE_WSTRING_SET &set_out, + const ACE_WString &pattern_in) = 0; + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. + + virtual int list_values (ACE_WSTRING_SET &set_out, + const ACE_WString &pattern_in) = 0; + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. + + virtual int list_types (ACE_WSTRING_SET &set_out, + const ACE_WString &pattern_in) = 0; + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. + + virtual int list_name_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) = 0; + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_value_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) = 0; + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_type_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) = 0; + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual void dump (void) const = 0; + // Dump the state of the object +}; + +#endif /* ACE_NAME_SPACE_H */ + diff --git a/ace/Naming_Context.cpp b/ace/Naming_Context.cpp new file mode 100644 index 00000000000..11f775a1498 --- /dev/null +++ b/ace/Naming_Context.cpp @@ -0,0 +1,531 @@ +// Naming_Context.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Get_Opt.h" +#include "ace/Naming_Context.h" +#include "ace/Remote_Name_Space.h" +#include "ace/Local_Name_Space.h" + +// Make life easier later on... + +typedef ACE_Local_Name_Space <ACE_MMAP_Memory_Pool, ACE_RW_Process_Mutex> LOCAL_NAME_SPACE; +typedef ACE_Local_Name_Space <ACE_Lite_MMAP_Memory_Pool, ACE_RW_Process_Mutex> LIGHT_LOCAL_NAME_SPACE; + +// The following Factory is used by the ACE_Service_Config and +// svc.conf file to dynamically initialize the state of the Name +// Server client. + +ACE_SVC_FACTORY_DEFINE (ACE_Naming_Context) + +// Define the object that describes the service statically. +ACE_STATIC_SVC_DEFINE (ACE_Naming_Context, + "ACE_Naming_Context", ACE_SVC_OBJ_T, &ACE_SVC_NAME (ACE_Naming_Context), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, 0) + +ACE_STATIC_SVC_REQUIRE (ACE_Naming_Context) + +int +ACE_Naming_Context::info (char **strp, + size_t length) const +{ + ACE_TRACE ("ACE_Naming_Context::info"); + char buf[BUFSIZ]; + + ACE_OS::sprintf (buf, "%s\t#%s\n", + "ACE_Naming_Context", + "Proxy for making calls to a Name Server"); + + if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, buf, length); + return ACE_OS::strlen (buf); +} + +int +ACE_Naming_Context::local (void) +{ + ACE_TRACE ("ACE_Naming_Context::local"); + return ACE_OS::strcmp (this->netnameserver_host_, "localhost") == 0 + || ACE_OS::strcmp (this->netnameserver_host_, this->hostname_) == 0; +} + +int +ACE_Naming_Context::open (Context_Scope_Type scope_in, int light) +{ + ACE_TRACE ("ACE_Naming_Context::open"); + ACE_OS::hostname (this->hostname_, sizeof this->hostname_); + + this->netnameserver_host_ = this->name_options_->nameserver_host (); + this->netnameserver_port_ = this->name_options_->nameserver_port (); + + // Perform factory operation to select appropriate type of + // Name_Space subclass. + + if (scope_in == ACE_Naming_Context::NET_LOCAL && this->local () == 0) + // Use NET_LOCAL name space, set up connection with remote server. + ACE_NEW_RETURN (this->name_space_, + ACE_Remote_Name_Space (this->netnameserver_host_, + this->netnameserver_port_), + -1); + else // Use NODE_LOCAL or PROC_LOCAL name space. + { + if (light) + ACE_NEW_RETURN (this->name_space_, LIGHT_LOCAL_NAME_SPACE (scope_in, this->name_options_), -1); + else + ACE_NEW_RETURN (this->name_space_, LOCAL_NAME_SPACE (scope_in, this->name_options_), -1); + } + return 0; +} + +int +ACE_Naming_Context::close (void) +{ + ACE_TRACE ("ACE_Naming_Context::close"); + + delete this->name_space_; + + return 0; +} + +ACE_Naming_Context::ACE_Naming_Context (void) +{ + ACE_TRACE ("ACE_Naming_Context::ACE_Naming_Context"); + ACE_NEW (this->name_options_, ACE_Name_Options); +} + +ACE_Naming_Context::ACE_Naming_Context (Context_Scope_Type scope_in, + int light) +{ + ACE_TRACE ("ACE_Naming_Context::ACE_Naming_Context"); + + ACE_NEW (this->name_options_, ACE_Name_Options); + + // Initialize. + if (this->open (scope_in, light) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Naming_Context::ACE_Naming_Context")); +} + +ACE_Name_Options * +ACE_Naming_Context::name_options (void) +{ + return this->name_options_; +} + +int +ACE_Naming_Context::bind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in) +{ + ACE_TRACE ("ACE_Naming_Context::bind"); + return this->name_space_->bind (name_in, value_in, type_in); +} + +int +ACE_Naming_Context::bind (const char *name_in, + const char *value_in, + const char *type_in) +{ + ACE_TRACE ("ACE_Naming_Context::bind"); + return this->bind (ACE_WString (name_in), ACE_WString (value_in), type_in); +} + +int +ACE_Naming_Context::rebind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in) +{ + ACE_TRACE ("ACE_Naming_Context::rebind"); + return this->name_space_->rebind (name_in, value_in, type_in); +} + +int +ACE_Naming_Context::rebind (const char *name_in, + const char *value_in, + const char *type_in) +{ + ACE_TRACE ("ACE_Naming_Context::rebind"); + return rebind (ACE_WString (name_in), ACE_WString (value_in), type_in); +} + +int +ACE_Naming_Context::resolve (const ACE_WString &name_in, + ACE_WString &value_out, + char *&type_out) +{ + ACE_TRACE ("ACE_Naming_Context::resolve"); + return this->name_space_->resolve (name_in, value_out, type_out); +} + +int +ACE_Naming_Context::resolve (const char *name_in, + ACE_WString &value_out, + char *&type_out) +{ + ACE_TRACE ("ACE_Naming_Context::resolve"); + return this->resolve (ACE_WString (name_in), value_out, type_out); +} + +int +ACE_Naming_Context::resolve (const char *name_in, + char *&value_out, + char *&type_out) +{ + ACE_TRACE ("ACE_Naming_Context::resolve"); + ACE_WString val_str; + + if (this->resolve (ACE_WString (name_in), val_str, type_out) == -1) + return -1; + + // Note that char_rep() *allocates* the memory! Thus, caller is + // responsible for deleting it! + value_out = val_str.char_rep (); + + return value_out == 0 ? -1 : 0; +} + +int +ACE_Naming_Context::unbind (const ACE_WString &name_in) +{ + ACE_TRACE ("ACE_Naming_Context::unbind"); + return this->name_space_->unbind (name_in); +} + +int +ACE_Naming_Context::unbind (const char *name_in) +{ + ACE_TRACE ("ACE_Naming_Context::unbind"); + return this->unbind (ACE_WString (name_in)); +} + +int +ACE_Naming_Context::list_names (ACE_PWSTRING_SET &set_out, + const ACE_WString &pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_names"); + return this->name_space_->list_names (set_out, pattern_in); +} + +int +ACE_Naming_Context::list_names (ACE_PWSTRING_SET &set_out, + const char *pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_names"); + return this->list_names (set_out, ACE_WString (pattern_in)); +} + +int +ACE_Naming_Context::list_values (ACE_PWSTRING_SET &set_out, + const ACE_WString &pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_values"); + return this->name_space_->list_values (set_out, pattern_in); +} + +int +ACE_Naming_Context::list_values (ACE_PWSTRING_SET &set_out, + const char *pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_values"); + return this->list_values (set_out, ACE_WString (pattern_in)); +} + +int +ACE_Naming_Context::list_types (ACE_PWSTRING_SET &set_out, + const ACE_WString &pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_types"); + return this->name_space_->list_types (set_out, pattern_in); +} + +int +ACE_Naming_Context::list_types (ACE_PWSTRING_SET &set_out, + const char *pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_types"); + return this->list_types (set_out, ACE_WString (pattern_in)); +} + +int +ACE_Naming_Context::list_name_entries (ACE_BINDING_SET &set_out, + const ACE_WString &pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_name_entries"); + return this->name_space_->list_name_entries (set_out, pattern_in); +} + +int +ACE_Naming_Context::list_name_entries (ACE_BINDING_SET &set_out, + const char *pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_name_entries"); + return this->list_name_entries (set_out, ACE_WString (pattern_in)); +} + +int +ACE_Naming_Context::list_value_entries (ACE_BINDING_SET &set_out, + const ACE_WString &pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_value_entries"); + return this->name_space_->list_value_entries (set_out, pattern_in); +} + +int +ACE_Naming_Context::list_value_entries (ACE_BINDING_SET &set_out, + const char *pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_value_entries"); + return this->list_value_entries (set_out, ACE_WString (pattern_in)); +} + +int +ACE_Naming_Context::list_type_entries (ACE_BINDING_SET &set_out, + const ACE_WString &pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_type_entries"); + return this->name_space_->list_type_entries (set_out, pattern_in); +} + +int +ACE_Naming_Context::list_type_entries (ACE_BINDING_SET &set_out, + const char *pattern_in) +{ + ACE_TRACE ("ACE_Naming_Context::list_type_entries"); + return this->list_type_entries (set_out, ACE_WString (pattern_in)); +} + + +ACE_Naming_Context::~ACE_Naming_Context (void) +{ + ACE_TRACE ("ACE_Naming_Context::~ACE_Naming_Context"); + delete this->name_space_; +} + +void +ACE_Naming_Context::dump () +{ + ACE_TRACE ("ACE_Naming_Context::dump"); + this->name_space_->dump(); +} + +int +ACE_Naming_Context::init (int argc, char *argv[]) +{ + ACE_DEBUG ((LM_DEBUG, "ACE_Naming_Context::init\n")); + this->name_options_->parse_args (argc, argv); + return this->open (this->name_options_->context ()); +} + +int +ACE_Naming_Context::fini (void) +{ + ACE_DEBUG ((LM_DEBUG, "ACE_Naming_Context::fini\n")); + delete this->name_options_; + return 0; +} + +ACE_Name_Options::ACE_Name_Options (void) + : debugging_ (0), + verbosity_ (0), + nameserver_port_ (ACE_DEFAULT_SERVER_PORT), + nameserver_host_ (ACE_OS::strdup (ACE_DEFAULT_SERVER_HOST)), + namespace_dir_ (ACE_OS::strdup (ACE_DEFAULT_NAMESPACE_DIR)), + process_name_ (0), + database_ (0) +{ + ACE_TRACE ("ACE_Name_Options::ACE_Name_Options"); +} + +ACE_Name_Options::~ACE_Name_Options (void) +{ + ACE_TRACE ("ACE_Name_Options::~ACE_Name_Options"); + + ACE_OS::free ((void *) this->nameserver_host_); + ACE_OS::free ((void *) this->namespace_dir_ ); + ACE_OS::free ((void *) this->process_name_ ); + ACE_OS::free ((void *) this->database_ ); +} + +void +ACE_Name_Options::nameserver_port (int port) +{ + ACE_TRACE ("ACE_Name_Options::nameserver_port"); + this->nameserver_port_ = port; +} + +int +ACE_Name_Options::nameserver_port (void) +{ + ACE_TRACE ("ACE_Name_Options::nameserver_port"); + return this->nameserver_port_; +} + +void +ACE_Name_Options::namespace_dir (const char *dir) +{ + ACE_TRACE ("ACE_Name_Options::namespace_dir"); + this->namespace_dir_ = ACE_OS::strdup (dir); +} + +void +ACE_Name_Options::process_name (const char *pname) +{ + ACE_TRACE ("ACE_Name_Options::process_name"); + const char *t = ACE::basename (pname, ACE_DIRECTORY_SEPARATOR_CHAR); + this->process_name_ = ACE_OS::strdup (t); +} + +void +ACE_Name_Options::nameserver_host (const char *host) +{ + ACE_TRACE ("ACE_Name_Options::nameserver_host"); + this->nameserver_host_ = ACE_OS::strdup (host); +} + +const char * +ACE_Name_Options::nameserver_host (void) +{ + ACE_TRACE ("ACE_Name_Options::nameserver_host"); + return this->nameserver_host_; +} + +const char * +ACE_Name_Options::database (void) +{ + ACE_TRACE ("ACE_Name_Options::database"); + return this->database_; +} + +void +ACE_Name_Options::database (const char *db) +{ + ACE_TRACE ("ACE_Name_Options::database"); + if (this->database_ != 0) + ACE_OS::free ((void *) this->database_); + this->database_ = ACE_OS::strdup (db); +} + +ACE_Naming_Context::Context_Scope_Type +ACE_Name_Options::context (void) +{ + ACE_TRACE ("ACE_Name_Options::context"); + return this->context_; +} + +void +ACE_Name_Options::context (ACE_Naming_Context::Context_Scope_Type context) +{ + ACE_TRACE ("ACE_Name_Options::context"); + this->context_ = context; +} + +const char * +ACE_Name_Options::process_name (void) +{ + ACE_TRACE ("ACE_Name_Options::process_name"); + return this->process_name_; +} + +const char * +ACE_Name_Options::namespace_dir (void) +{ + ACE_TRACE ("ACE_Name_Options::namespace_dir"); + return this->namespace_dir_; +} + +int +ACE_Name_Options::debug (void) +{ + ACE_TRACE ("ACE_Name_Options::debug"); + return this->debugging_; +} + +int +ACE_Name_Options::verbose (void) +{ + ACE_TRACE ("ACE_Name_Options::verbose"); + return this->verbosity_; +} + +void +ACE_Name_Options::parse_args (int argc, char *argv[]) +{ + ACE_TRACE ("ACE_Name_Options::parse_args"); + ACE_LOG_MSG->open (argv[0]); + this->process_name (argv[0]); + + // Default is to use the PROC_LOCAL context... + this->context (ACE_Naming_Context::PROC_LOCAL); + + // Make the database name the same as the process name by default + // (note that this makes a copy of the process_name_ so that we can + // clean it up in the destructor). + this->database (this->process_name ()); + + ACE_Get_Opt get_opt (argc, argv, "c:dh:l:P:p:s:T:v"); + + for (int c; (c = get_opt ()) != -1; ) + switch (c) + { + case 'c': + { + if (ACE_OS::strcmp (get_opt.optarg, "PROC_LOCAL")) + this->context (ACE_Naming_Context::PROC_LOCAL); + else if (ACE_OS::strcmp (get_opt.optarg, "NODE_LOCAL")) + this->context (ACE_Naming_Context::NODE_LOCAL); + else if (ACE_OS::strcmp (get_opt.optarg, "NET_LOCAL")) + this->context (ACE_Naming_Context::NET_LOCAL); + } + break; + case 'd': + this->debugging_ = 1; + break; + case 'h': + this->nameserver_host (get_opt.optarg); + break; + case 'l': + this->namespace_dir (get_opt.optarg); + break; + case 'P': + this->process_name (get_opt.optarg); + break; + case 'p': + this->nameserver_port (ACE_OS::atoi (get_opt.optarg)); + break; + case 's': + this->database (get_opt.optarg); + break; + case 'T': + if (ACE_OS::strcasecmp (get_opt.optarg, "ON") == 0) + ACE_Trace::start_tracing (); + else if (ACE_OS::strcasecmp (get_opt.optarg, "OFF") == 0) + ACE_Trace::stop_tracing (); + break; + case 'v': + this->verbosity_ = 1; + break; + default: + ACE_OS::fprintf (stderr, "%s\n" + "\t[-d] (enable debugging)\n" + "\t[-h nameserver host]\n" + "\t[-l namespace directory]\n" + "\t[-P processname]\n" + "\t[-p nameserver port]\n" + "\t[-s database name]\n" + "\t[-v] (verbose) \n", + argv[0]); + /* NOTREACHED */ + break; + } +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Local_Name_Space <ACE_MMAP_Memory_Pool, ACE_RW_Process_Mutex>; +template class ACE_Local_Name_Space <ACE_Lite_MMAP_Memory_Pool, ACE_RW_Process_Mutex>; +template class ACE_Allocator_Adapter<ACE_Malloc<ACE_MMAP_Memory_Pool, ACE_RW_Process_Mutex> >; +template class ACE_Allocator_Adapter<ACE_Malloc<ACE_Lite_MMAP_Memory_Pool, ACE_RW_Process_Mutex> >; +ACE_Name_Space_Map <ACE_Allocator_Adapter <ACE_Malloc <ACE_MMAP_Memory_Pool, ACE_RW_Process_Mutex> > >; +ACE_Name_Space_Map <ACE_Allocator_Adapter <ACE_Malloc <ACE_Lite_MMAP_Memory_Pool, ACE_RW_Process_Mutex> > >; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Naming_Context.h b/ace/Naming_Context.h new file mode 100644 index 00000000000..a1c483e855f --- /dev/null +++ b/ace/Naming_Context.h @@ -0,0 +1,312 @@ +/* -*- C++ -*- */ +// $Id$ + +/*-*- C++ -*- */ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Naming_Context.h +// +// = AUTHOR +// Gerhard Lenzer, Douglas C. Schmidt, and Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_NAMING_CONTEXT_H) +#define ACE_NAMING_CONTEXT_H + +#include "ace/ACE.h" +#include "ace/SString.h" +#include "ace/Set.h" +#include "ace/Service_Object.h" +#include "ace/Name_Proxy.h" +#include "ace/Name_Space.h" + +// Forward decl +class ACE_Name_Options; + +class ACE_Export ACE_Naming_Context : public ACE_Service_Object + // = TITLE + // Maintaining accesses Name Server Databases. Allows to add + // NameBindings, change them, remove them and resolve + // NameBindings + // + // = DESCRIPTION + // Manages a Naming Service . That represents a persistent + // string to string mapping for different scopes. The scope of a + // ACE_Naming_Context may be either local for the calling + // process (Note : A process is hereby not identified by it's + // pid, but by it's argv[0]. So different processes (in UNIX + // syntax) may access the same NameBindings), global for all + // processes running on one host or global for all processes on + // the net (that know the address of the net name server + // socket). Strings may be plain character strings or Wide + // character strings. A Name Binding consists of a name string + // (that's the key), a value string and an optional type string + // (no wide chars). +{ +public: + enum Context_Scope_Type + { + PROC_LOCAL, // Name lookup is local to the process. + NODE_LOCAL, // Name lookup is local to the node (host). + NET_LOCAL // Name lookup is local to the (sub)network. + }; + + // = Initialization and termination methods. + ACE_Naming_Context (void); + // "Do-nothing" constructor. + + ACE_Naming_Context (Context_Scope_Type scope_in, int light = 0); + // Specifies the scope of this namespace, opens and memory-maps the + // associated file (if accessible) or contacts the dedicated name + // server process for NET_LOCAL namespace. Note that <light> + // specifies whether or not we want to use + // ACE_Lite_MMap_Memory_Pool. By default we use ACE_MMap_Memory_Pool. + + int open (Context_Scope_Type scope_in = ACE_Naming_Context::PROC_LOCAL, + int light = 0); + // Specifies the scope of this namespace, opens and memory-maps the + // associated file (if accessible) or contacts the dedicated name + // server process for NET_LOCAL namespace. Note that <light> + // specifies whether or not we want to use + // ACE_Lite_MMap_Memory_Pool. By default we use ACE_MMap_Memory_Pool. + + int close (void); + // Deletes the instance of Name Space. Must be called before + // switching name spaces. + + ~ACE_Naming_Context (void); + // destructor, do some cleanup :TBD: last dtor should "compress" + // file + + // = Dynamic initialization hooks. + virtual int init (int argc, char *argv[]); + // Initialize name options and naming context when dynamically + // linked. + + virtual int fini (void); + // Close down the test when dynamically unlinked. + + virtual int info (char **strp, size_t length) const; + // Returns information about this context. + + ACE_Name_Options *name_options (void); + // Returns the ACE_Name_Options associated with the Naming_Context + + int bind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in = ""); + // Bind a new name to a naming context (Wide character strings). + + int bind (const char *name_in, + const char *value_in, + const char *type_in = ""); + // Bind a new name to a naming context ( character strings). + + int rebind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in = ""); + // Overwrite the value or type of an existing name in a + // ACE_Naming_Context or bind a new name to the context, if it + // didn't exist yet. (Wide charcter strings interface). + + int rebind (const char *name_in, + const char *value_in, + const char *type_in = ""); + // Overwrite the value or type of an existing name in a + // ACE_Naming_Context or bind a new name to the context, if it + // didn't exist yet. ( charcter strings interface) + + int unbind (const ACE_WString &name_in); + // Delete a name from a ACE_Naming_Context (Wide charcter strings + // Interface). + + int unbind (const char *name_in); + // Delete a name from a ACE_Naming_Context (character strings + // interface). + + int resolve (const ACE_WString &name_in, + ACE_WString &value_out, + char *&type_out); + // Get value and type of a given name binding (Wide chars). The + // caller is responsible for deleting both <value_out> and <type_out>! + + int resolve (const char *name_in, + ACE_WString &value_out, + char *&type_out); + // Get value and type of a given name binding (Wide chars output). + // The caller is responsible for deleting both <value_out> and + // <type_out>! + + int resolve (const char *name_in, + char *&value_out, + char *&type_out); + // Get value and type of a given name binding ( chars ). The caller + // is responsible for deleting both <value_out> and <type_out>! + + int list_names (ACE_PWSTRING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. + + int list_names (ACE_PWSTRING_SET &set_out, + const char *pattern_in); + // Get a set of names matching a specified pattern (chars). Matching + // means the names must begin with the pattern string. + + int list_values (ACE_PWSTRING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. + + int list_values (ACE_PWSTRING_SET &set_out, + const char *pattern_in); + // Get a set of values matching a specified pattern (chars). Matching + // means the values must begin with the pattern string. + + int list_types (ACE_PWSTRING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. + + int list_types (ACE_PWSTRING_SET &set_out, + const char *pattern_in); + // Get a set of types matching a specified pattern (chars). Matching + // means the types must begin with the pattern string. + + virtual int list_name_entries (ACE_BINDING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_name_entries (ACE_BINDING_SET &set_out, + const char *pattern_in); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_value_entries (ACE_BINDING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_value_entries (ACE_BINDING_SET &set_out, + const char *pattern_in); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_type_entries (ACE_BINDING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_type_entries (ACE_BINDING_SET &set_out, + const char *pattern_in); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + void dump (); + // Dump the state of the object. + +private: + ACE_Name_Options *name_options_; + // Keep track of the options such as database name etc per Naming Context + + ACE_Name_Space *name_space_; + // Name space (can be either local or remote) dynamically bound. + + char hostname_[MAXHOSTNAMELEN + 1]; + // Holds the local hostname. + + const char *netnameserver_host_; + // Holds name of net name server. + + int netnameserver_port_; + // Holds port number of the net name server. + + int local (void); + // 1 if we're on the same local machine as the name server, else 0. + +}; + +class ACE_Export ACE_Name_Options + // = TITLE + // Manages the options for the ACE Name_Server. +{ +public: + // = Initialization and termination methods. + ACE_Name_Options (void); + ~ACE_Name_Options (void); + + void parse_args (int argc, char *argv[]); + // Parse arguments + + // = Set/Get port number + void nameserver_port (int port); + int nameserver_port (void); + + // = Set/Get the context + ACE_Naming_Context::Context_Scope_Type context (void); + void context (ACE_Naming_Context::Context_Scope_Type); + + // = Set/Get host name + void nameserver_host (const char *host); + const char *nameserver_host (void); + + // = Set/Get name space directory + void namespace_dir (const char *dir); + const char *namespace_dir (void); + + // = Set/Get process name + void process_name (const char *dir); + const char *process_name (void); + + // = Set/Get database name + void database (const char *db); + const char *database (void); + + int debug (void); + // Return debug status + + int verbose (void); + // Return verbose status + +private: + int debugging_; + // Extra debugging info + + int verbosity_; + // Extra verbose messages + + int nameserver_port_; + // Port to connect to nameserver process. + + const char *nameserver_host_; + // Hostname of nameserver. + + const char *namespace_dir_; + // Directory to hold name_bindings. + + const char *process_name_; + // Name of this process. + + const char *database_; + // Name of the database that stores the name/value/type bindings. + + ACE_Naming_Context::Context_Scope_Type context_; + // The context in which the naming database will be created. +}; + +extern "C" ACE_Export ACE_Service_Object *_make_ACE_Naming_Context (void); + +#endif /* ACE_NAMING_CONTEXT_H */ diff --git a/ace/OS.cpp b/ace/OS.cpp new file mode 100644 index 00000000000..a55b8fa99c8 --- /dev/null +++ b/ace/OS.cpp @@ -0,0 +1,1224 @@ +// $Id$ + +// OS.cpp +#define ACE_BUILD_DLL +#include "ace/OS.h" + +#include "ace/Log_Msg.h" +#include "ace/ARGV.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 "ace/OS.i" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +void +ACE_OS::flock_t::dump (void) const +{ +// ACE_TRACE ("ACE_OS::flock_t::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "handle_ = %u", this->handle_)); +#if defined (ACE_WIN32) + ACE_DEBUG ((LM_DEBUG, "\nInternal = %d", this->overlapped_.Internal)); + ACE_DEBUG ((LM_DEBUG, "\nInternalHigh = %d", this->overlapped_.InternalHigh)); + ACE_DEBUG ((LM_DEBUG, "\nOffsetHigh = %d", this->overlapped_.OffsetHigh)); + ACE_DEBUG ((LM_DEBUG, "\nhEvent = %d", this->overlapped_.hEvent)); +#else + ACE_DEBUG ((LM_DEBUG, "\nl_whence = %d", this->lock_.l_whence)); + ACE_DEBUG ((LM_DEBUG, "\nl_start = %d", this->lock_.l_start)); + ACE_DEBUG ((LM_DEBUG, "\nl_len = %d", this->lock_.l_len)); + ACE_DEBUG ((LM_DEBUG, "\nl_type = %d", this->lock_.l_type)); +#endif /* ACE_WIN32 */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_OS::mutex_lock_cleanup (void *mutex) +{ +// ACE_TRACE ("ACE_OS::mutex_lock_cleanup"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex; + ACE_OS::mutex_unlock (p_lock); +#endif /* ACE_HAS_DCETHREADS */ +#endif /* ACE_HAS_THREADS */ +} + +// = 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 +// is implemented as a structure... +ACE_thread_t ACE_OS::NULL_thread; + +ACE_OS::ACE_OS (void) +{ +// ACE_TRACE ("ACE_OS::ACE_OS"); +} + +#if defined (ACE_WIN32) + +// = Static initialization. + +// Keeps track of whether we've initialized the WinSock DLL. +int ACE_OS::socket_initialized_; + +// We need this to initialize the WinSock DLL. + +BOOL WINAPI +DllMain (HINSTANCE, // DLL module handle + DWORD fdwReason, // Reason called + LPVOID) // Reserved +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + if (ACE_OS::socket_init (ACE_WSOCK_VERSION) != 0) + return FALSE; + break; + + case DLL_PROCESS_DETACH: + if (ACE_OS::socket_fini () != 0) + return FALSE; + break; + + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + + default: + ACE_ERROR_RETURN ((LM_ERROR, + "Sock.DLL DllMain called with unknown fdwReason = %u\n.", + fdwReason), FALSE); + /* NOTREACHED */ + } + + return TRUE; +} + +#include "ace/Synch.h" +#include "ace/Set.h" + +class ACE_TSS_Ref + // = TITLE + // "Reference count" for thread-specific storage keys. + // + // = DESCRIPTION + // Since the ACE_Unbounded_Set doesn't allow duplicates, the + // "reference count" is the identify of the thread_id. +{ +public: + ACE_TSS_Ref (ACE_thread_t id); + // Constructor + + ACE_TSS_Ref (void); + // Default constructor + + int operator== (const ACE_TSS_Ref &); + // Check for equality. + +// private: + + ACE_thread_t tid_; + // ID of thread using a specific key. +}; + +ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id) + : tid_(id) +{ +// ACE_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref"); +} + +ACE_TSS_Ref::ACE_TSS_Ref (void) +{ +// ACE_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref"); +} + +// Check for equality. +int +ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) +{ +// ACE_TRACE ("ACE_TSS_Ref::operator=="); + + return this->tid_ == info.tid_; +} + +typedef ACE_Unbounded_Set<ACE_TSS_Ref> ACE_TSS_REF_TABLE; +typedef ACE_Unbounded_Set_Iterator<ACE_TSS_Ref> ACE_TSS_REF_TABLE_ITERATOR; + +class ACE_TSS_Info + // = TITLE + // Thread Specific Key management. + // + // = DESCRIPTION + // This class maps a key to a "destructor." +{ +public: + ACE_TSS_Info (ACE_thread_key_t key, + void (*dest)(void *) = 0, + void *tss_inst = 0); + // Constructor + + ACE_TSS_Info (void); + // Default constructor + + int operator== (const ACE_TSS_Info &); + // Check for equality. + + void dump (void); + // Dump the state. + +// private: + ACE_thread_key_t key_; + // Key to the thread-specific storage item. + + void (*destructor_)(void *); + // "Destructor" that gets called when the item is finally released. + + void *tss_obj_; + // Pointer to ACE_TSS<xxx> instance that has/will allocate the key. + + ACE_TSS_REF_TABLE ref_table_; + // Table of thread IDs that are using this key. +}; + +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) +{ +// ACE_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); +} + +ACE_TSS_Info::ACE_TSS_Info (void) +{ +// ACE_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); +} + +// Check for equality. +int +ACE_TSS_Info::operator== (const ACE_TSS_Info &info) +{ +// ACE_TRACE ("ACE_TSS_Info::operator=="); + + return this->key_ == info.key_; +} + +void +ACE_TSS_Info::dump (void) +{ +// ACE_TRACE ("ACE_TSS_Info::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "key_ = %u", this->key_)); + ACE_DEBUG ((LM_DEBUG, "\ndestructor_ = %u", this->destructor_)); + ACE_DEBUG ((LM_DEBUG, "\ntss_obj_ = %u", this->tss_obj_)); + ACE_DEBUG ((LM_DEBUG, "\nref_table_.size_ = %u", this->ref_table_.size ())); + + ACE_TSS_Ref *tid_info = 0; + + ACE_DEBUG ((LM_DEBUG, "\nThread_usage_list\n[\n")); + + for (ACE_TSS_REF_TABLE_ITERATOR iter (this->ref_table_); + iter.next (tid_info) != 0; + iter.advance ()) + ACE_DEBUG ((LM_DEBUG, "\ntid_ = %d", tid_info->tid_)); + + ACE_DEBUG ((LM_DEBUG, "\n]\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// Create a set of <ACE_TSS_Info> objects that will reside +// within thread-specific storage. +typedef ACE_Unbounded_Set<ACE_TSS_Info> ACE_TSS_TABLE; +typedef ACE_Unbounded_Set_Iterator<ACE_TSS_Info> ACE_TSS_TABLE_ITERATOR; + +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); + + void exit (void *status); + // Cleanup the thread-specific objects and exit with <status>. + + int insert (ACE_thread_key_t key, void (*destructor)(void *), void *inst); + // Insert a <key, destructor> tuple into the table. + + int remove (ACE_thread_key_t key); + // Remove a <key, destructor> tuple from the table. + + int detach (void *inst); + // Detaches a tss_instance from its key. + + int detach (ACE_thread_key_t key, ACE_thread_t tid); + // Detaches a thread from the key. + + int key_used (ACE_thread_key_t key); + // Mark a key as being used by this thread. + +protected: + void dump (void); + + ACE_TSS_Cleanup (void); + // Ensure singleton. + +private: + ACE_TSS_TABLE table_; + // Table of <ACE_TSS_Info>'s. + + // = Static data. + static ACE_TSS_Cleanup *instance_; + // Pointer to the singleton instance. + +public: + static ACE_Recursive_Thread_Mutex lock_; + // Serialize initialization of <key_>. +}; + +// = Static object initialization. + +// Pointer to the singleton instance. +ACE_TSS_Cleanup *ACE_TSS_Cleanup::instance_ = 0; + +// Serialize initialization of <key_>. +ACE_Recursive_Thread_Mutex ACE_TSS_Cleanup::lock_; + +void +ACE_TSS_Cleanup::exit (void *status) +{ +// ACE_TRACE ("ACE_TSS_Cleanup::exit"); + + { + ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_); + + // Prevent recursive deletions (note that when a recursive mutex + // is first acquired it has a nesting level of 1...). + if (ACE_TSS_Cleanup::lock_.get_nesting_level () > 1) + return; + + ACE_thread_key_t key_arr[TLS_MINIMUM_AVAILABLE]; + int index = 0; + + ACE_TSS_Info *key_info = 0; + + // Iterate through all the thread-specific items and free them all + // up. + + for (ACE_TSS_TABLE_ITERATOR iter (this->table_); + iter.next (key_info) != 0; + iter.advance ()) + { + void *tss_info = 0; + + int val = key_info->ref_table_.remove (ACE_TSS_Ref (ACE_OS::thr_self ())); + + if ((ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0) + && (key_info->destructor_) + && tss_info) + // Probably need to have an exception handler here... + (*key_info->destructor_) (tss_info); + + if (key_info->ref_table_.size () == 0 + && key_info->tss_obj_ == 0) + key_arr[index++] = key_info->key_; + } + + for (int i = 0; i < index; i++) + { + ::TlsFree (key_arr[i]); + this->table_.remove (ACE_TSS_Info (key_arr[i])); + } + } + +#if 0 + ::ExitThread ((DWORD) status); +#endif + ::_endthreadex ((DWORD) status); + + /* NOTREACHED */ +} + +ACE_TSS_Cleanup::ACE_TSS_Cleanup (void) +{ +// ACE_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup"); +} + +ACE_TSS_Cleanup * +ACE_TSS_Cleanup::instance (void) +{ +// ACE_TRACE ("ACE_TSS_Cleanup::instance"); + + // Create and initialize thread-specific key. + if (ACE_TSS_Cleanup::instance_ == 0) + { + // Insure that we are serialized! + ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, 0); + + // Now, use the Double-Checked Locking pattern to make sure we + // only create the key once. + if (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_TRACE ("ACE_TSS_Cleanup::insert"); + ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); + + return this->table_.insert (ACE_TSS_Info (key, destructor, inst)); +} + +int +ACE_TSS_Cleanup::remove (ACE_thread_key_t key) +{ +// ACE_TRACE ("ACE_TSS_Cleanup::remove"); + ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); + + return this->table_.remove (ACE_TSS_Info (key)); +} + +int +ACE_TSS_Cleanup::detach (void *inst) +{ + ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); + + ACE_TSS_Info *key_info = 0; + int success = 0; + int ref_cnt = 0; + + for (ACE_TSS_TABLE_ITERATOR iter (this->table_); + iter.next (key_info) != 0; + iter.advance ()) + { + if (key_info->tss_obj_ == inst) + { + key_info->tss_obj_ = 0; + ref_cnt = key_info->ref_table_.size (); + success = 1; + break; + } + } + + if (success == 0) + return -1; + else if (ACE_TSS_Cleanup::lock_.get_nesting_level () > 1) + ACE_ERROR_RETURN ((LM_DEBUG, "Detach() invoked from ACE_TSS_Cleanup::exit()\n"), 0); + else if (ref_cnt == 0) + { + ::TlsFree (key_info->key_); + return this->table_.remove (ACE_TSS_Info (key_info->key_)); + } + + return 0; +} + +int +ACE_TSS_Cleanup::detach (ACE_thread_key_t key, ACE_thread_t tid) +{ + return -1; +} + +int +ACE_TSS_Cleanup::key_used (ACE_thread_key_t key) +{ + ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); + + ACE_TSS_Info *key_info = 0; + + for (ACE_TSS_TABLE_ITERATOR iter (this->table_); + iter.next (key_info) != 0; + iter.advance ()) + if (key_info->key_ == key) + return key_info->ref_table_.insert (ACE_TSS_Ref (ACE_OS::thr_self ())); + + return -1; +} + +void +ACE_TSS_Cleanup::dump (void) +{ + ACE_TSS_Info *key_info = 0; + + // Iterate through all the thread-specific items and dump them all. + + for (ACE_TSS_TABLE_ITERATOR iter (this->table_); + iter.next (key_info) != 0; + iter.advance ()) + key_info->dump (); +} + +// Special thread startup argument (used below in <thr_create>). + +class ACE_Win32_Thread_Adapter +{ +public: + ACE_Win32_Thread_Adapter (ACE_THR_FUNC f, void *a); + // Constructor + + static void *svc_run (ACE_Win32_Thread_Adapter *); + // Run the thread exit point. + +private: + // = Arguments to thread startup. + ACE_THR_FUNC func_; + // Thread startup function. + + void *arg_; + // Argument to thread startup function. +}; + +ACE_Win32_Thread_Adapter::ACE_Win32_Thread_Adapter (ACE_THR_FUNC f, void *a) + : func_(f), + arg_(a) +{ +// ACE_TRACE ("ACE_Win32_Thread_Adapter::ACE_Win32_Thread_Adapter"); +} + +void * +ACE_Win32_Thread_Adapter::svc_run (ACE_Win32_Thread_Adapter *thread_args) +{ +// ACE_TRACE ("ACE_Win32_Thread_Adapter::svc_run"); + ACE_THR_FUNC func = thread_args->func_; + void *arg = thread_args->arg_; + delete thread_args; + void *status; + + ACE_SEH_TRY { + status = (*func) (arg); // Call thread entry point. + } + ACE_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { + // Here's where we might want to provide a hook to report this... + // As it stands now, we just catch all Win32 structured exceptions + // so that we can make sure to clean up correctly when the thread + // exits. + } + + // If dropped off end, call destructors for thread-specific storage + // and exit. + ACE_TSS_Cleanup::instance ()->exit (status); + + /* NOTREACHED */ + return status; +} + +#endif // WIN32 + +int +ACE_OS::thr_create (ACE_THR_FUNC func, + void *args, + long flags, + ACE_thread_t *thr_id, + ACE_hthread_t *thr_handle, + u_int priority, + void *stack, + size_t stacksize) +{ +// ACE_TRACE ("ACE_OS::thr_create"); + +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + int result; + pthread_attr_t attr; + ACE_thread_t tmp_thr; + ACE_thread_t *p_thr; + +#if defined (ACE_HAS_SETKIND_NP) + if (::pthread_attr_create (&attr) != 0) +#else /* ACE_HAS_SETKIND_NP */ + if (::pthread_attr_init (&attr) != 0) +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + else if (priority != 0) + { + struct sched_param sparam; + + ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); + +#if defined (ACE_HAS_DCETHREADS) && !defined (ACE_HAS_SETKIND_NP) + sparam.sched_priority = priority > PRIORITY_MAX ? PRIORITY_MAX : priority; +#elif defined(ACE_HAS_IRIX62_THREADS) + sparam.sched_priority = priority > PTHREAD_MAX_PRIORITY ? PTHREAD_MAX_PRIORITY : priority; +#elif defined (PTHREAD_MAX_PRIORITY) // For MIT pthreads... + sparam.prio = priority > PTHREAD_MAX_PRIORITY ? PTHREAD_MAX_PRIORITY : priority; +#endif /* ACE_HAS_DCETHREADS */ + +#if !defined (ACE_HAS_FSU_PTHREADS) +#if defined (ACE_HAS_SETKIND_NP) + if (::pthread_attr_setsched (&attr, SCHED_OTHER) != 0) +#else /* ACE_HAS_SETKIND_NP */ + if (::pthread_attr_setschedparam (&attr, &sparam) != 0) +#endif /* ACE_HAS_SETKIND_NP */ + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } +#else + if ((sparam.sched_priority >= PTHREAD_MIN_PRIORITY) + && (sparam.sched_priority <= PTHREAD_MAX_PRIORITY)) + attr.prio = sparam.sched_priority; + else + { + pthread_attr_destroy (&attr); + return -1; + } +#endif // ACE_HAS_FSU_PTHREADS + } + + if (stacksize != 0) + { + size_t size = stacksize; + +#if defined (PTHREAD_STACK_MIN) + if (size < PTHREAD_STACK_MIN) + stacksize = PTHREAD_STACK_MIN; +#endif /* PTHREAD_STACK_MIN */ + + if (::pthread_attr_setstacksize (&attr, size) != 0) + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } + } + +#if !defined (ACE_LACKS_THREAD_STACK_ADDR) + if (stack != 0) + { + if (::pthread_attr_setstackaddr (&attr, stack) != 0) + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } + } +#endif /* !ACE_LACKS_THREAD_STACK_ADDR */ + if (flags != 0) + { +#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_SETKIND_NP) + if (::pthread_attr_setdetach_np (&attr, dstate) != 0) +#else /* ACE_HAS_SETKIND_NP */ + if (::pthread_attr_setdetachstate (&attr, dstate) != 0) +#endif /* ACE_HAS_SETKIND_NP */ + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } + } +#endif /* ACE_LACKS_SETDETACH */ + 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 (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + spolicy = SCHED_OTHER; + else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) + spolicy = SCHED_FIFO; + else + spolicy = SCHED_RR; + +#if !defined (ACE_HAS_FSU_PTHREADS) +#if defined (ACE_HAS_SETKIND_NP) + if (::pthread_attr_setsched (&attr, spolicy) != 0) +#else /* ACE_HAS_SETKIND_NP */ + if (::pthread_attr_setschedpolicy (&attr, spolicy) != 0) +#endif /* ACE_HAS_SETKIND_NP */ + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } +#else + int ret; + switch (spolicy) + { + case SCHED_FIFO: + case SCHED_RR: + ret = 0; + break; + default: + ret = 22; + break; + } + if (ret != 0) + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } +#endif // ACE_HAS_FSU_PTHREADS + } + + if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED) + || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED)) + { +#if defined (ACE_HAS_SETKIND_NP) + int sched = PTHREAD_DEFAULT_SCHED; +#else /* ACE_HAS_SETKIND_NP */ + int sched = PTHREAD_EXPLICIT_SCHED; +#endif /* ACE_HAS_SETKIND_NP */ + if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)) + sched = PTHREAD_INHERIT_SCHED; + if (::pthread_attr_setinheritsched (&attr, sched) != 0) + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + return -1; + } + } +#if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING) + if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM) + || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS)) + { + int scope = PTHREAD_SCOPE_PROCESS; + if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)) + scope = PTHREAD_SCOPE_SYSTEM; + + if (::pthread_attr_setscope (&attr, scope) != 0) + { +#if defined (ACE_HAS_SETKIND_NP) + ::pthread_attr_delete (&attr); +#else /* ACE_HAS_SETKIND_NP */ + ::pthread_attr_destroy (&attr); +#endif /* ACE_HAS_SETKIND_NP */ + 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 + // Solaris semantics. + int lwps = ACE_OS::thr_getconcurrency (); + ACE_OS::thr_setconcurrency (lwps + 1); + } + } + + p_thr = (thr_id == 0 ? &tmp_thr : thr_id); + +#if defined (ACE_HAS_SETKIND_NP) + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (p_thr, attr, func, args), + result), + int, -1, result); + ::pthread_attr_delete (&attr); + if (thr_handle != 0) + thr_handle = (ACE_hthread_t *) 0; +#else /* ACE_HAS_SETKIND_NP */ + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (p_thr, &attr, func, args), + result), + int, -1, result); + ::pthread_attr_destroy (&attr); + if (thr_handle != 0) + *thr_handle = (ACE_hthread_t) 0; +#endif /* ACE_HAS_SETKIND_NP */ + + return result; +#elif defined (ACE_HAS_STHREADS) + int result; + ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize, func, args, + flags, thr_id), result), + int, -1, result); + if (result == 0 && thr_handle != 0) + *thr_handle = *thr_id; + return result; +#elif defined (ACE_HAS_WTHREADS) + ACE_thread_t t; + ACE_hthread_t handle; + + if (thr_id == 0) + thr_id = &t; + if (thr_handle == 0) + thr_handle = &handle; + + ACE_Win32_Thread_Adapter *thread_args; + + ACE_NEW_RETURN (thread_args, ACE_Win32_Thread_Adapter (func, args), -1); + + typedef unsigned (__stdcall *ThreadFunc) (void*); + +#if defined (ACE_HAS_MFC) + if (ACE_BIT_ENABLED (flags, THR_USE_AFX)) + { + CWinThread *cwin_thread = + // These aren't the right arguments (yet). + ::AfxBeginThread ((ThreadFunc) (ACE_Win32_Thread_Adapter::svc_run), + thread_args, 0, 0, flags); + *thr_handle = cwin_thread->m_hThread; + *thr_id = cwin_thread->m_nThreadID; + // Can we delete the memory of cwin_thread here? + } + else +#endif /* ACE_HAS_MFC */ + *thr_handle = (void *) ::_beginthreadex + (NULL, + stacksize, + (ThreadFunc) (ACE_Win32_Thread_Adapter::svc_run), + thread_args, + flags, + (unsigned int *) thr_id); + +#if 0 + *thr_handle = ::CreateThread + (NULL, stacksize, + LPTHREAD_START_ROUTINE (ACE_Win32_Thread_Adapter::svc_run), + thread_args, flags, thr_id); +#endif /* 0 */ + + // Close down the handle if no one wants to use it. + if (thr_handle == &handle) + ::CloseHandle (thr_handle); + + if (*thr_handle != 0) + return 0; + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +#elif defined (VXWORKS) + // If thr_id points to NULL (or is 0), the call below causes VxWorks + // to assign a unique task name of the form: "t" + an integer. + + // args must be an array of _exactly_ 10 ints. + + // stack arg is ignored: if there's a need for it, we'd have to use + // taskInit ()/taskActivate () instead of taskSpawn () + + // The hard-coded arguments are what ::sp() would use. ::taskInit() + // is used instead of ::sp() so that we can set the priority, flags, + // and stacksize. (::sp() also hardcodes priority to 100, flags + // to VX_FP_TASK, and stacksize to 20,000.) stacksize should be + // an even integer. + + // if called with thr_create() defaults, use same default values as ::sp() + if ( stacksize == 0 ) stacksize = 20000; + if ( priority == 0 ) priority = 100; + + ACE_hthread_t tid = ::taskSpawn (thr_id == 0 ? NULL : *thr_id, priority, + (int) flags, (int) stacksize, func, + ((int *) args)[0], ((int *) args)[1], + ((int *) args)[2], ((int *) args)[3], + ((int *) args)[4], ((int *) args)[5], + ((int *) args)[6], ((int *) args)[7], + ((int *) args)[8], ((int *) args)[9]); + + if ( tid == ERROR ) + return -1; + else + { + // return the thr_id and thr_handle, if addresses were provided for them + if ( thr_id != 0 ) + // 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 + // would be a bit quicker than this extraction of the tcb . . . + *thr_id = taskTcb (tid)->name; + if ( thr_handle != 0 ) + *thr_handle = tid; + return 0; + } + +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +void +ACE_OS::thr_exit (void *status) +{ +// ACE_TRACE ("ACE_OS::thr_exit"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ::pthread_exit (status); +#elif defined (ACE_HAS_STHREADS) + ::thr_exit (status); +#elif defined (ACE_HAS_WTHREADS) + // Cleanup the thread-specific resources and exit. + ACE_TSS_Cleanup::instance ()->exit (status); +#elif defined (VXWORKS) + *((int *) status) = ::taskDelete (ACE_OS::thr_self ()); +#endif /* ACE_HAS_STHREADS */ +#else + ; +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data) +{ +// ACE_TRACE ("ACE_OS::thr_setspecific"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || 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), _result), + int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) + ::TlsSetValue (key, data); + ACE_TSS_Cleanup::instance ()->key_used (key); + return 0; +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::thr_keyfree (ACE_thread_key_t key) +{ +// ACE_TRACE ("ACE_OS::thr_keyfree"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_LACKS_KEYDELETE) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_PTHREADS) && !defined (ACE_HAS_FSU_PTHREADS) + return ::pthread_key_delete (key); +#elif defined (ACE_HAS_DCETHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_STHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + // Extract out the thread-specific table instance and and free up + // the key and destructor. + ACE_TSS_Cleanup::instance ()->remove (key); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), _result), int, -1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::thr_keycreate (ACE_thread_key_t *key, + void (*dest) (void *), + void *inst) +{ +// ACE_TRACE ("ACE_OS::thr_keycreate"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) +#if defined (ACE_HAS_SETKIND_NP) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_keycreate (key, dest), + _result), + int, -1); +#else /* ACE_HAS_SETKIND_NP */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest), + _result), + int, -1); +#endif /* ACE_HAS_SETKIND_NP */ +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest), + _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 */ + +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::thr_key_used (ACE_thread_key_t key) +{ +#if defined (ACE_WIN32) + return ACE_TSS_Cleanup::instance ()->key_used (key); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::thr_key_detach (void *inst) +{ +#if defined (ACE_WIN32) + return ACE_TSS_Cleanup::instance()->detach (inst); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +// Create a contiguous command-line argument buffer with each arg +// separated by spaces. + +pid_t +ACE_OS::fork_exec (char *argv[]) +{ +#if defined (ACE_WIN32) + ACE_ARGV argv_buf (argv); + + char *buf = argv_buf.buf (); + + if (buf != 0) + { + PROCESS_INFORMATION process_info; + STARTUPINFO startup_info; + ACE_OS::memset ((void *) &startup_info, 0, sizeof startup_info); + startup_info.cb = sizeof startup_info; + + if (::CreateProcess (NULL, + buf, + NULL, // No process attributes. + NULL, // No thread attributes. + TRUE, // Allow handle inheritance. + CREATE_NEW_CONSOLE, // Create a new console window. + NULL, // No environment. + NULL, // No current directory. + &startup_info, + &process_info)) + { + // Free resources allocated in kernel. + ACE_OS::close (process_info.hThread); + ACE_OS::close (process_info.hProcess); + // Return new process id. + return process_info.dwProcessId; + } + } + + // CreateProcess failed. + return -1; +#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) + { + 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 */ + } + +#if defined (ACE_NEEDS_WRITEV) + +// "Fake" writev for sites without it. Note that this is totally +// broken for multi-threaded applications since the <send_n> calls are +// not atomic... + +extern "C" int +writev (ACE_HANDLE handle, ACE_WRITEV_TYPE *vp, int vpcount) +{ +// ACE_TRACE ("::writev"); + + int count; + + for (count = 0; --vpcount >= 0; count += vp->iov_len, vp++) + if (ACE::send_n (handle, vp->iov_base, vp->iov_len) < 0) + return -1; + + return count; +} +#endif /* ACE_NEEDS_WRITEV */ + +#if defined (ACE_NEEDS_READV) + +// "Fake" readv for sites without it. Note that this is totally +// broken for multi-threaded applications since the <send_n> calls are +// not atomic... + +extern "C" int +readv (ACE_HANDLE handle, struct iovec *vp, int vpcount) +{ +// ACE_TRACE ("::readv"); + + int count; + + for (count = 0; --vpcount >= 0; count += vp->iov_len, vp++) + if (ACE::recv_n (handle, vp->iov_base, vp->iov_len) < 0) + return -1; + + return count; +} +#endif /* ACE_NEEDS_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 ::fcntl (handle, F_FREESP, &fl); +} +#endif /* ACE_NEEDS_FTRUNCATE */ + +char * +ACE_OS::mktemp (char *s) +{ + // ACE_TRACE ("ACE_OS::mktemp"); +#if defined (ACE_LACKS_MKTEMP) + if (s == 0) + // check for null template string failed! + return 0; + else + { + char *xxxxxx = ACE_OS::strstr (s, "XXXXXX"); + + if (xxxxxx == 0) + // the template string doesn't contain "XXXXXX"! + return s; + else + { + char unique_letter = 'a'; + struct 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 + // Solaris 2.5 mktemp(). + ::sprintf (xxxxxx, "%05d%c", getpid (), unique_letter); + while (::stat (s, &sb) >= 0) + { + if (++unique_letter <= 'z') + ::sprintf (xxxxxx, "%05d%c", getpid (), unique_letter); + else + { + // maximum of 26 unique files per template, per process + ::sprintf (xxxxxx, "%s", ""); + return s; + } + } + } + return s; + } + +#else + return ::mktemp (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) + ACE_ERROR_RETURN ((LM_ERROR, + "WSAStartup failed, WSAGetLastError returned %u.\n", + error), -1); + + ACE_OS::socket_initialized_ = 1; + } +#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 (); + ACE_ERROR_RETURN ((LM_ERROR, + "WSACleanup failed, WSAGetLastError returned %u.\n", + error), -1); + } + ACE_OS::socket_initialized_ = 0; + } +#endif /* ACE_WIN32 */ + return 0; +} + +#if defined (VXWORKS) +int sys_nerr = ERRMAX + 1; +#endif /* VXWORKS */ diff --git a/ace/OS.h b/ace/OS.h new file mode 100644 index 00000000000..f573e507310 --- /dev/null +++ b/ace/OS.h @@ -0,0 +1,2174 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// OS.h +// +// = AUTHOR +// Doug Schmidt <schmidt@cs.wustl.edu>, Jesper S. M|ller +// <stophph@diku.dk>, and a cast of thousands... +// +// ============================================================================ + +#if !defined (ACE_OS_H) +#define ACE_OS_H + +// Define the default constants for ACE. Many of these are used for +// the ACE tests and applications. You may want to change some of +// these to correspond to your environment. + +#define ACE_DEFAULT_TIMEOUT 5 +#define ACE_DEFAULT_THREADS 1 + +// The following 3 defines are used in the IP multicast and broadcast tests. +#define ACE_DEFAULT_BROADCAST_PORT 10000 +#define ACE_DEFAULT_MULTICAST_PORT 10001 +#define ACE_DEFAULT_MULTICAST_ADDR "224.9.9.2" + +// Used in many IPC_SAP tests +#define ACE_DEFAULT_SERVER_PORT 10002 + +// Used in Acceptor tests +#define ACE_DEFAULT_SERVER_PORT_STR "10002" + +// Used for the Service_Directory test +#define ACE_DEFAULT_SERVICE_PORT 10003 + +// Used for the ACE_Thread_Spawn test +#define ACE_DEFAULT_THR_PORT 10004 + +// Used for SOCK_Connect::connect() tests +#define ACE_DEFAULT_LOCAL_PORT 10005 + +// Used for Connector tests +#define ACE_DEFAULT_LOCAL_PORT_STR "10005" + +// Used for the name server. +#define ACE_DEFAULT_NAME_SERVER_PORT 10006 +#define ACE_DEFAULT_NAME_SERVER_PORT_STR "10006" + +// Used for the token server. +#define ACE_DEFAULT_TOKEN_SERVER_PORT 10007 +#define ACE_DEFAULT_TOKEN_SERVER_PORT_STR "10007" + +// Used for the logging server. +#define ACE_DEFAULT_LOGGING_SERVER_PORT 10008 +#define ACE_DEFAULT_LOGGING_SERVER_PORT_STR "10008" + +// Used for the logging server. +#define ACE_DEFAULT_THR_LOGGING_SERVER_PORT 10008 +#define ACE_DEFAULT_THR_LOGGING_SERVER_PORT_STR "10008" + +// Used for the time server. +#define ACE_DEFAULT_TIME_SERVER_PORT 10010 +#define ACE_DEFAULT_TIME_SERVER_PORT_STR "10010" +#define ACE_DEFAULT_TIME_SERVER_STR "ACE_TS_TIME" + +#define ACE_DEFAULT_SERVER_HOST "localhost" + +// Default shared memory key +#define ACE_DEFAULT_SHM_KEY 1234 + +// Default address for shared memory mapped files and SYSV shared memory +// (defaults to 64 M). +#define ACE_DEFAULT_BASE_ADDR ((char *) (64 * 1024 * 1024)) + +// Default segment size used by SYSV shared memory (128 K) +#define ACE_DEFAULT_SEGMENT_SIZE 1024 * 128 + +// Maximum number of SYSV shared memory segments +// (does anyone know how to figure out the right values?!) +#define ACE_DEFAULT_MAX_SEGMENTS 6 + +// Used by the FIFO tests. +#define ACE_DEFAULT_RENDEZVOUS "/tmp/fifo.ace" + +// Name of the map that's stored in shared memory. +#define ACE_NAME_SERVER_MAP "Name Server Map" + +// Default file permissions. +#define ACE_DEFAULT_PERMS 0666 + +// Default size of the ACE Reactor. +#define ACE_DEFAULT_REACTOR_SIZE FD_SETSIZE + +// Default size of the ACE Map_Manager. +#define ACE_DEFAULT_MAP_SIZE 1024 + +// Here are all ACE-specific global declarations needed throughout +// ACE. + +// Helpful dump macros. +#define ACE_BEGIN_DUMP "\n====\n(%P|%t|%x)" +#define ACE_END_DUMP "====\n" + +// This is used to indicate that a platform doesn't support a +// particular feature. +#define ACE_NOTSUP_RETURN(FAILVALUE) do { errno = ENOTSUP ; return FAILVALUE; } while (0) + +#if defined (ACE_NDEBUG) +#define ACE_DB(X) +#else +#define ACE_DB(X) X +#endif /* ACE_NDEBUG */ + +// 10 millisecond fudge factor to account for Solaris timers... +#define ACE_TIMER_SKEW 1000 * 10 + +// 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) +#define ACE_SYNCH_1 class ACE_SYNCH +#define ACE_SYNCH_2 ACE_SYNCH +#define ACE_SYNCH_MUTEX ACE_SYNCH::ACE_MUTEX +#define ACE_SYNCH_CONDITION ACE_SYNCH::ACE_CONDITION +#else /* TEMPLATES are broken (must be a cfront-based compiler...) */ +#define ACE_SYNCH_1 class ACE_SYNCH_MUTEX, class ACE_SYNCH_CONDITION +#define ACE_SYNCH_2 ACE_SYNCH_MUTEX, ACE_SYNCH_CONDITION +#define ACE_SYNCH_MUTEX ACE_SYNCH_MUTEX +#define ACE_SYNCH_CONDITION ACE_SYNCH_CONDITION +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + +// Increase the range of "address families". +#define AF_SPIPE (AF_MAX + 1) +#define AF_FILE (AF_MAX + 2) +#define AF_DEV (AF_MAX + 3) +#define AF_UPIPE (AF_SPIPE) + +// 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)?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_SET_BITS(WORD, BITS) (WORD |= (BITS)) +#define ACE_CLR_BITS(WORD, BITS) (WORD &= ~(BITS)) + +// A useful abstraction for expressions involving operator new since +// we can change memory allocation error handling policies (e.g., +// depending on whether ANSI/ISO exception handling semantics are +// being used). + +#define ACE_NEW(POINTER,CONSTRUCTOR) \ + do { POINTER = new CONSTRUCTOR; \ + if (POINTER == 0) { errno = ENOMEM; return; }} while (0) +#define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ + do { POINTER = new CONSTRUCTOR; \ + if (POINTER == 0) { errno = ENOMEM; return RET_VAL; }} while (0) + +// These hooks enable ACE to have all dynamic memory management +// automatically handled on a per-object basis. + +#if defined (ACE_HAS_ALLOC_HOOKS) +#define ACE_ALLOC_HOOK_DECLARE \ + void *operator new (size_t bytes); \ + void operator delete (void *ptr); + +// Note that these are just place holders for now. They'll +// be replaced by the ACE_Malloc stuff shortly... +#define ACE_ALLOC_HOOK_DEFINE(CLASS) \ + void *CLASS::operator new (size_t bytes) { return ::new char[bytes]; } \ + void CLASS::operator delete (void *ptr) { delete (ptr); } +#else +#define ACE_ALLOC_HOOK_DECLARE struct __Ace {} // Just need a dummy... +#define ACE_ALLOC_HOOK_DEFINE(CLASS) +#endif /* ACE_HAS_ALLOC_HOOKS */ + +#include "ace/Time_Value.h" + +// 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 */ + +// Static service macros +#define ACE_STATIC_SVC_DECLARE(X) extern ACE_Static_Svc_Descriptor ace_svc_desc_##X ; +#define ACE_STATIC_SVC_DEFINE(X, NAME, TYPE, FN, FLAGS, ACTIVE) \ +ACE_Static_Svc_Descriptor ace_svc_desc_##X = { NAME, TYPE, FN, FLAGS, ACTIVE }; +#define ACE_STATIC_SVC_REQUIRE(X)\ +class ACE_Static_Svc_##X {\ +public:\ + ACE_Static_Svc_##X() { ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_##X); }\ +};\ +static ACE_Static_Svc_##X ace_static_svc_##X; + +// Dynamic/static service macros. +#define ACE_SVC_FACTORY_DECLARE(X) extern "C" ACE_Svc_Export ACE_Service_Object *_make_##X (void); +#define ACE_SVC_INVOKE(X) _make_##X () +#define ACE_SVC_NAME(X) _make_##X +#define ACE_SVC_FACTORY_DEFINE(X) ACE_Service_Object *_make_##X () { ACE_TRACE (#X); return new X; } + +#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) +#define ACE_TSS_TYPE(T) T +#define ACE_TSS_GET(I, T) (I) +#else +#define ACE_TSS_TYPE(T) ACE_TSS< T > +#define ACE_TSS_GET(I, T) ((I)->operator T * ()) +#endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */ + +#if defined (ACE_LACKS_MODE_MASKS) +// MODE MASKS + +// the following macros are for POSIX conformance. + +#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. +#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 +{ + u_short sem_num; // semaphore # + short sem_op; // semaphore operation + short sem_flg; // operation flags +}; +#endif /* ACE_LACKS_SEMBUF_T */ + +#if defined (ACE_LACKS_UTSNAME_T) +#define _SYS_NMLN 257 +struct utsname +{ + char sysname[_SYS_NMLN]; + char nodename[_SYS_NMLN]; + char release[_SYS_NMLN]; + char version[_SYS_NMLN]; + char machine[_SYS_NMLN]; +}; +#endif /* ACE_LACKS_UTSNAME_T */ + +#if defined (ACE_HAS_H_ERRNO) +void herror (const char *str); +#endif /* ACE_HAS_H_ERRNO */ + +#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 <sys/procfs.h> +#endif /* ACE_HAS_PROC_FD */ + +#if defined (ACE_HAS_UNICODE) +#include <wchar.h> +#endif /* ACE_HAS_UNICODE */ + +#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_SETRLIMIT) +typedef struct rlimit ACE_SETRLIMIT_TYPE; +#else +typedef const struct rlimit ACE_SETRLIMIT_TYPE; +#endif /* ACE_HAS_BROKEN_SETRLIMIT */ + +#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 */ + +struct ACE_Export ACE_Str_Buf + // = TITLE + // Simple wrapper for STREAM pipes strbuf. +{ + int maxlen; + // Number of bytes in buffer. + + int len; + // Number of bytes returned. + + void *buf; + // Pointer to data. + + // = Initialization method + ACE_Str_Buf (void *b = 0, int l = 0, int max = 0); + // Constructor. +}; + +#if defined (ACE_MT_SAFE) +#define ACE_MT(X) X +#if !defined (_REENTRANT) +#define _REENTRANT +#endif /* _REENTRANT */ +#else +#define ACE_MT(X) +#endif /* ACE_MT_SAFE */ + +// These are the various states a thread managed by the +// <Thread_Manager> can be in. +enum ACE_Thread_State +{ + ACE_THR_IDLE, + // Uninitialized. + + ACE_THR_SPAWNED, + // Created but not yet running. + + ACE_THR_RUNNING, + // Thread is active (naturally, we don't know if it's actually + // *running* because we aren't the scheduler...). + + ACE_THR_SUSPENDED, + // Thread is suspended. + + ACE_THR_CANCELLED, + // Thread has been cancelled (which is an indiction that it needs to + // terminate...). + + ACE_THR_TERMINATED + // Thread has shutdown, but the slot in the thread manager hasn't + // been reclaimed yet. +}; + +// Convenient macro for testing for deadlock, as well as for detecting +// when mutexes fail. +#define ACE_GUARD_RETURN(MUTEX,OBJ,LOCK,RETURN) \ + ACE_Guard<MUTEX> OBJ (LOCK); \ + if (OBJ.locked () == 0) return 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_RETURN(MUTEX,OBJ,LOCK,RETURN) \ + ACE_Read_Guard<MUTEX> OBJ (LOCK); \ + if (OBJ.locked () == 0) return RETURN; +#define ACE_GUARD(MUTEX,OBJ,LOCK) \ + ACE_Guard<MUTEX> OBJ (LOCK); \ + if (OBJ.locked () == 0) return; + +#if defined (ACE_HAS_POSIX_SEM) +#include <semaphore.h> +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). +} ACE_sema_t; +#endif /* ACE_HAS_POSIX_SEM */ + +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) +#include <synch.h> +#include <thread.h> +#endif /* ACE_HAS_STHREADS */ + +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_DCETHREADS) || defined (ACE_HAS_PTHREADS) +// Definitions for mapping POSIX pthreads onto Solaris threads. + +#if defined (ACE_HAS_FSU_PTHREADS) +#define PTHREAD_DETACHED 0x1 +#define PTHREAD_SCOPE_SYSTEM 0x2 +#define PTHREAD_INHERIT_SCHED 0x4 +#define PTHREAD_NOFLOAT 0x8 +#define PTHREAD_CREATE_UNDETACHED 0 +#define PTHREAD_CREATE_DETACHED PTHREAD_DETACHED +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_EXPLICIT_SCHED 0 +#define PTHREAD_MIN_PRIORITY 0 +#define PTHREAD_MAX_PRIORITY 126 +#endif // ACE_HAS_FSU_PTHREADS + +#if defined (ACE_HAS_SETKIND_NP) +#define PRIORITY_MAX PTHREAD_MAX_PRIORITY +#endif /* ACE_HAS_SETKIND_NP */ + +#if !defined (ACE_HAS_TID_T) +typedef pthread_t tid_t; +#endif /* ACE_HAS_TID_T */ + +// Typedefs to help compatibility with Windows NT and Pthreads. +#if defined (ACE_HAS_PTHREAD_T) +typedef pthread_t ACE_hthread_t; +#else /* ACE_HAS_PTHREAD_T */ +typedef tid_t ACE_hthread_t; +#endif /* ACE_HAS_PTHREAD_T */ + +// Make it easier to write portable thread code. +typedef pthread_t ACE_thread_t; +typedef pthread_key_t ACE_thread_key_t; +typedef pthread_mutex_t ACE_mutex_t; +typedef pthread_cond_t ACE_cond_t; +typedef pthread_mutex_t ACE_thread_mutex_t; + +#if (!defined (timespec) && !defined (m88k)) +#define timestruc_t struct timespec +#endif /* timespec */ + +#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_PROCESS_PRIVATE) +#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) +#if defined (PTHREAD_MUTEXTYPE_FAST) +#define PTHREAD_PROCESS_SHARED PTHREAD_MUTEXTYPE_FAST +#else +#define PTHREAD_PROCESS_SHARED 0 +#endif /* PTHREAD_MUTEXTYPE_FAST */ +#endif /* PTHREAD_PROCESS_SHARED */ + +#if defined (ACE_HAS_DCETHREADS) +#if defined (PTHREAD_PROCESS_PRIVATE) +#define USYNC_THREAD PTHREAD_PROCESS_PRIVATE +#else +#define USYNC_THREAD MUTEX_NONRECURSIVE_NP +#endif /* PTHREAD_PROCESS_PRIVATE */ + +#if defined (PTHREAD_PROCESS_SHARED) +#define USYNC_PROCESS PTHREAD_PROCESS_SHARED +#else +#define USYNC_PROCESS MUTEX_NONRECURSIVE_NP +#endif /* PTHREAD_PROCESS_SHARED */ +#elif !defined (ACE_HAS_STHREADS) +#define USYNC_THREAD PTHREAD_PROCESS_PRIVATE +#define USYNC_PROCESS PTHREAD_PROCESS_SHARED +#endif /* ACE_HAS_DCETHREADS */ + +#define THR_BOUND 0x00000001 +#define THR_NEW_LWP 0x00000002 +#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_USE_AFX 0x01000000 + +#if !defined (ACE_HAS_STHREADS) +#if !defined (ACE_HAS_POSIX_SEM) +// This is used to implement semaphores for POSIX pthreads, but +// without POSIX semaphores. It is different than the POSIX sem_t. +struct ACE_sema_t +{ + ACE_mutex_t lock_; + ACE_cond_t count_nonzero_; + u_long count_; +}; +#endif /* !ACE_HAS_POSIX_SEM */ + +// This is used to implement readers/writer locks for POSIX pthreads. +struct ACE_rwlock_t +{ + 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. +}; +#else +// If we are on Solaris we can just reuse the existing implementations +// of these synchronization types. +typedef rwlock_t ACE_rwlock_t; +#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) +// 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; +typedef rwlock_t ACE_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; +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 +#elif defined(VXWORKS) + +#include <semLib.h> // for mutex implementation using mutual-exclusion + // semaphores (which can be taken recursively) +#include <taskLib.h> + +// 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 USYNC_THREAD 0 +#define USYNC_PROCESS 1 // it's all global on VxWorks (without MMU + // option) + +typedef SEM_ID ACE_mutex_t; +// implement ACE_thread_mutex_t with ACE_mutex_t sinces there's just one process . . . +typedef ACE_mutex_t ACE_thread_mutex_t; +#if !defined (ACE_HAS_POSIX_SEM) +// although ACE_HAS_POSIX_SEM is assumed for VxWorks +typedef semaphore * ACE_sema_t; +#endif /* !ACE_HAS_POSIX_SEM */ +typedef char * ACE_thread_t; +typedef int ACE_hthread_t; +typedef int ACE_thread_key_t; + +struct ACE_cond_t + // = TITLE + // This structure is used to implement condition variables on VxWorks + // + // = DESCRIPTION + // At the current time, this stuff only works for threads + // within the same process, which there's only one of on VxWorks. +{ + long waiters_; + // Number of waiting threads. + + ACE_sema_t sema_; + // Queue up threads waiting for the condition to become signaled. +}; + +struct ACE_rwlock_t + // = TITLE + // This is used to implement readers/writer locks on VxWorks + // + // = DESCRIPTION + // At the current time, this stuff only works for threads + // within the same process, which there's only one of on VxWorks. +{ + 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. +}; + +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else /* !ACE_HAS_THREADS, i.e., the OS/platform doesn't support threading. */ +// Give these things some reasonable value... +#define THR_CANCEL_DISABLE 0 +#define THR_CANCEL_ENABLE 0 +#define THR_CANCEL_DEFERRED 0 +#define THR_CANCEL_ASYNCHRONOUS 0 +#define THR_DETACHED 0 // ?? ignore in most places +#define THR_BOUND 0 // ?? ignore in most places +#define THR_NEW_LWP 0 // ?? ignore in most places +#define THR_SUSPENDED 0 // ?? ignore in most places +#define USYNC_THREAD 0 +#define USYNC_PROCESS 0 +// These are dummies needed for class OS.h +typedef int ACE_cond_t; +typedef int ACE_mutex_t; +typedef int ACE_thread_mutex_t; +#if !defined (ACE_HAS_POSIX_SEM) +typedef int ACE_sema_t; +#endif /* !ACE_HAS_POSIX_SEM */ +typedef int ACE_rwlock_t; +typedef int ACE_thread_t; +typedef int ACE_hthread_t; +typedef int ACE_thread_key_t; +#endif /* ACE_HAS_THREADS */ + +#include <sys/types.h> +#include <assert.h> +#include <sys/stat.h> +#include <limits.h> +#include <stdio.h> +#include <new.h> +#include <ctype.h> +#include <signal.h> +#include <string.h> +#include <iostream.h> +#include <stdarg.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> + +// This must come after signal.h is #included. +#if defined (SCO) +#define SIGIO SIGPOLL +#undef sigemptyset +#undef sigfillset +#undef sigaddset +#undef sigdelset +#undef sigismember +#endif /* SCO */ + +#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.x version of rand_r is inconsistent with the header files... +typedef unsigned int ACE_RANDR_TYPE; +extern "C" int rand_r (ACE_RANDR_TYPE seed); +#else +typedef unsigned int *ACE_RANDR_TYPE; +#endif /* ACE_HAS_BROKEN_RANDR */ + +#if !defined (ACE_HAS_RTLD_LAZY_V) +#define RTLD_LAZY 1 +#endif /* !ACE_HAS_RTLD_LAZY_V */ + +#if defined (ACE_HAS_UTIME) +#include <utime.h> +#endif /* ACE_HAS_UTIME */ + +#if !defined (ACE_HAS_MSG) && !defined (SCO) +struct msghdr {}; +#endif /* ACE_HAS_MSG */ + +#if !defined (ACE_HAS_HI_RES_TIMER) +typedef int hrtime_t; +#endif /* ACE_HAS_HI_RES_TIMER */ + +#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_OLD_MALLOC) +typedef char *ACE_MALLOC_T; +#else +typedef void *ACE_MALLOC_T; +#endif /* ACE_HAS_OLD_MALLOC */ + +#if defined (ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES) +// Prototypes for both signal() and struct sigaction are consistent.. +typedef void (*ACE_SignalHandler)(int); +typedef void (*ACE_SignalHandlerV)(int); +#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)(void); +typedef void (*ACE_SignalHandlerV)(void); +#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 */ +#define ACE_SignalHandler SIG_PF +typedef void (*ACE_SignalHandlerV)(...); +#endif /* ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES */ + +#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 +#ifndef ALL_WARNINGS +// #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 +#endif //!ALL_WARNINGS +// We're on WinNT or Win95 +#define ACE_PLATFORM "Win32" +#define ACE_PLATFORM_EXE_SUFFIX ".exe" + +#include <sys/timeb.h> + +// The following 3 defines are used by the ACE Name Server... +#define ACE_DEFAULT_NAMESPACE_DIR "C:\\temp" +#define ACE_DEFAULT_LOCALNAME "\\localnames" +#define ACE_DEFAULT_GLOBALNAME "\\globalnames" + +// Used for ACE_MMAP_Memory_Pool +#define ACE_DEFAULT_BACKING_STORE "C:\\temp\\ace-malloc-XXXXXX" + +// Used for logging +#define ACE_DEFAULT_LOGFILE "C:\\temp\\logfile" + +// Used for dynamic linking +#define ACE_DEFAULT_SVC_CONF ".\\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 +#define ACE_DEFAULT_SEM_KEY "ACE_SEM_KEY" +#define ACE_INVALID_SEM_KEY 0 +#define ACE_DEFAULT_MUTEX "ACE_MUTEX" + +// This flag speeds up the inclusion of Win32 header files. +#if !defined (WIN32_LEAN_AND_MEAN) +#define WIN32_LEAN_AND_MEAN 1 +#endif /* !defined (WIN32_LEAN_AND_MEAN) */ + +#define ACE_SEH_TRY __try +#define ACE_SEH_EXCEPT(X) __except(X) + +// The "null" device on Win32. +#define ACE_DEV_NULL "nul" + +// Define the pathname separator characters for Win32 (ugh). +#define ACE_DIRECTORY_SEPARATOR_STR "\\" +#define ACE_DIRECTORY_SEPARATOR_CHAR '\\' +#define ACE_LD_SEARCH_PATH "PATH" +#define ACE_LD_SEARCH_PATH_SEPARATOR_STR ";" + +// 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 shmid_ds { }; +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; +}; + +// Win32 doesn't use numeric values to name its semaphores, it uses +// strings! +typedef char *key_t; + +// 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 */ + +// This is necessary since MFC users apparently can't #include +// <windows.h> directly. +#if !defined (__AFX_H__) +#include <windows.h> +#endif /* __AFX_H__ */ + +#include <winsock.h> + +#define MAXHOSTNAMELEN (MAX_COMPUTERNAME_LENGTH+1) // This should be around 16 or so... + +// 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 + +#include <time.h> +#include <direct.h> +#include <process.h> +#include <io.h> + +typedef OVERLAPPED ACE_OVERLAPPED; +typedef DWORD ACE_thread_t; +typedef HANDLE ACE_hthread_t; +typedef long pid_t; +typedef DWORD ACE_thread_key_t; +typedef DWORD nlink_t; + +// 64-bit quad-word definitions +#if !defined (_MSC_VER) /* Borland? */ +typedef uint64 ACE_QWORD; +inline ACE_QWORD ACE_MAKE_QWORD (DWORD lo, DWORD hi) { return unit64 (lo, hi); } +inline DWORD ACE_LOW_DWORD (ACE_QWORD q) { return q.LowPart; } +inline DWORD ACE_HIGH_DWORD (ACE_QWORD q) { return q.HighPart; } +#else +typedef unsigned __int64 ACE_QWORD; +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); } +#endif /* !defined (_MSC_VER) */ + +// Win32 dummys to help compilation + +typedef void *sigset_t; // Who knows? +typedef int mode_t; +typedef CRITICAL_SECTION ACE_thread_mutex_t; +typedef struct +{ + int type_; // Either USYNC_THREAD or USYNC_PROCESS + union + { + HANDLE proc_mutex_; + CRITICAL_SECTION thr_mutex_; + }; +} ACE_mutex_t; +typedef HANDLE ACE_sema_t; +typedef int uid_t; +typedef int gid_t; +typedef int hrtime_t; +typedef char *caddr_t; + +struct ACE_cond_t + // = TITLE + // This structure is used to implement condition variables on NT. + // + // = DESCRIPTION + // At the current time, this stuff only works for threads + // within the same process. +{ + DWORD waiters_; + // Number of waiting threads. + + ACE_sema_t sema_; + // Queue up threads waiting for the condition to become signaled. +}; + +struct ACE_rwlock_t + // = TITLE + // This is used to implement readers/writer locks on NT. + // + // = DESCRIPTION + // At the current time, this stuff only works for threads + // within the same process. +{ + 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. +}; + +// Wrapper for NT Events. +typedef HANDLE ACE_event_t; + +// This is for file descriptors. +typedef HANDLE ACE_HANDLE; + +// For Win32 compatibility. +typedef SOCKET ACE_SOCKET; + +#define ACE_INVALID_HANDLE INVALID_HANDLE_VALUE +#define ACE_SYSCALL_FAILED 0xFFFFFFFF + +// 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 0 // ?? ignore in most places +#define THR_BOUND 0 // ?? ignore in most places +#define THR_NEW_LWP 0 // ?? ignore in most places +#define THR_SUSPENDED CREATE_SUSPENDED + +// 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 0 +#define MAXPATHLEN _MAX_PATH +#define MAXNAMLEN _MAX_FNAME +#define EADDRINUSE WSAEADDRINUSE + +// Undefined structs becomes undeclared overloads with MSVC++ 2.0 +// Thus we need to resort to this for unsupported system calls. + +struct sigaction +{ + int sa_flags; + ACE_SignalHandlerV sa_handler; + sigset_t sa_mask; +}; + +struct iovec +{ + char *iov_base; // data to be read/written + size_t iov_len; // byte count to read/write +}; + +struct rlimit { }; +struct t_call { }; +struct t_bind { }; +struct t_info { }; +struct t_optmgmt { }; +struct t_discon { }; +struct t_unitdata { }; +struct t_uderr { }; +struct netbuf { }; +struct flock { }; // not used with Win32 locking... + +// Deal with whatever UNICODE mapping the application is compiling +// with! + +#else /* !defined (ACE_WIN32) */ + +// We're some kind of UNIX... +#define ACE_PLATFORM "UNIX" +#define ACE_PLATFORM_EXE_SUFFIX "" + +typedef const char *LPCTSTR; +typedef char *LPTSTR; +typedef char TCHAR; + +#if defined (m88k) +#define RUSAGE_SELF 1 +#endif // m88k + +// Default semaphore key +#define ACE_DEFAULT_SEM_KEY 1234 +#define ACE_INVALID_SEM_KEY -1 +#define ACE_DEFAULT_MUTEX "ACE_MUTEX" + +// The following 3 defines are used by the ACE Name Server... +#define ACE_DEFAULT_NAMESPACE_DIR "/tmp" +#define ACE_DEFAULT_LOCALNAME "/localnames" +#define ACE_DEFAULT_GLOBALNAME "/globalnames" + +// Used for ACE_MMAP_Memory_Pool +#define ACE_DEFAULT_BACKING_STORE "/tmp/ace-malloc-XXXXXX" + +// Used for logging +#define ACE_DEFAULT_LOGFILE "/tmp/logfile" + +// Used for dynamic linking. +#define ACE_DEFAULT_SVC_CONF "./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 +#define ACE_INVALID_HANDLE -1 +#define ACE_SYSCALL_FAILED -1 + +#define ACE_SEH_TRY +#define ACE_SEH_EXCEPT(X) + +// The "null" device on UNIX. +#define ACE_DEV_NULL "/dev/null" + +// Define the pathname separator characters for UNIX. +#define ACE_DIRECTORY_SEPARATOR_STR "/" +#define ACE_DIRECTORY_SEPARATOR_CHAR '/' +#define ACE_LD_SEARCH_PATH "LD_LIBRARY_PATH" +#define ACE_LD_SEARCH_PATH_SEPARATOR_STR ":" + +// Wrapper for NT events on UNIX. +struct ACE_event_t +{ + ACE_mutex_t lock_; + // Protect critical section. + + ACE_cond_t condition_; + // Keeps track of waiters. + + int manual_reset_; + // Specifies if this is an auto- or manual-reset event. + + int is_signaled_; + // "True" if signaled. + + u_long waiting_threads_; + // Number of waiting threads. +}; + +// Provide compatibility with Windows NT. +typedef int ACE_HANDLE; +// For Win32 compatibility. +typedef ACE_HANDLE ACE_SOCKET; + +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... +typedef int LPSECURITY_ATTRIBUTES; +#define GENERIC_READ 0 +#define FILE_SHARE_READ 0 +#define OPEN_EXISTING 0 +#define FILE_ATTRIBUTE_NORMAL 0 +#define MAXIMUM_WAIT_OBJECTS 0 +#define FILE_FLAG_OVERLAPPED 0 + +#if defined (ACE_HAS_BROKEN_IF_HEADER) +struct ifafilt; +#endif +#include <sys/socket.h> +extern "C" { +#if !defined (VXWORKS) +#include <netdb.h> +#endif /* VXWORKS */ +#include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> +} +#if defined (VXWORKS) +#include <sys/times.h> +#else +#include <sys/param.h> +#include <sys/uio.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> +#include <sys/file.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <pwd.h> +#endif /* VXWORKS */ +#include <sys/ioctl.h> +#include <dirent.h> +#include <sys/utsname.h> +#include <sys/stat.h> +#include <unistd.h> + +#if !defined (ACE_LACKS_PARAM_H) +#include <sys/param.h> +#endif /* ACE_LACKS_PARAM_H */ + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) && !defined (VXWORKS) +#include <sys/un.h> +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ + +#if defined (ACE_HAS_SIGINFO_T) +#if !defined (ACE_LACKS_SIGINFO_H) +#include <siginfo.h> +#endif /* ACE_LACKS_SIGINFO_H */ +#if !defined (ACE_LACKS_UCONTEXT_H) +#include <ucontext.h> +#endif /* ACE_LACKS_UCONTEXT_H */ +#endif /* ACE_HAS_SIGINFO_T */ + +#if defined (ACE_HAS_POLL) +#include <poll.h> +#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 <stropts.h> +#undef _XOPEN_EXTENDED_SOURCE +#else +#include <stropts.h> +#endif /* AIX */ +#endif /* ACE_HAS_STREAMS */ + +#if defined (ACE_LACKS_T_ERRNO) +extern int t_errno; +#endif /* ACE_LACKS_T_ERRNO */ + +#if !defined (ACE_HAS_SIGWAIT) +extern "C" int sigwait (sigset_t *set); +#endif /* ACE_HAS_SIGWAIT */ + +#if defined (ACE_HAS_SELECT_H) +#include <sys/select.h> +#endif /* ACE_HAS_SELECT_H */ + +#if defined (ACE_HAS_ALLOCA_H) +#include <alloca.h> +#endif /* ACE_HAS_ALLOCA_H */ + +#if defined (ACE_HAS_TIUSER_H) +#include <tiuser.h> +#endif /* ACE_HAS_TIUSER_H */ + +#if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) +#include <dlfcn.h> +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ + +#if defined (ACE_HAS_SOCKIO_H) +#include <sys/sockio.h> +#endif /* ACE_HAS_SOCKIO_ */ + +#if defined (ACE_HAS_TIMOD_H) +#include <sys/timod.h> +#elif defined (ACE_HAS_OSF_TIMOD_H) +#include <tli/timod.h> +#endif /* ACE_HAS_TIMOD_H */ + +// There must be a better way to do this... +#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) */ + +#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(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 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, char *buf, unsigned 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 */ + +// IRIX5 defines bzero() in this odd file... +#if defined (ACE_HAS_BSTRING) +#include <bstring.h> +#endif /* ACE_HAS_BSTRING */ + +// AIX defines bzero() in this odd file... +#if defined (ACE_HAS_STRINGS) +#include <strings.h> +#endif /* ACE_HAS_STRINGS */ + +#if defined (ACE_HAS_TERM_IOCTLS) +#include <sys/termios.h> +#endif /* ACE_HAS_TERM_IOCTLS */ + +#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 <sys/mman.h> +} +#elif !defined (ACE_LACKS_MMAP) +#include <sys/mman.h> +#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 (VXWORKS) +#include <sys/msg.h> +#endif /* VXWORKS */ +#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 */ +#endif /* ACE_WIN32 */ + +#if defined (VXWORKS) +typedef int key_t; + +#include <vxWorks.h> + +#if defined (ACE_HAS_GREENHILLS_SOCKETS) +#include <hostLib.h> +#include <ioLib.h> +#include <selectLib.h> +#include <sigLib.h> +#include <sockLib.h> + +extern "C" +struct sockaddr_un { + short sun_family; // AF_UNIX. + char sun_path[108]; // path name. +}; +#endif /* ACE_HAS_GREENHILLS_SOCKETS */ + +#define MAXPATHLEN 1024 +#define MAXNAMLEN 255 +#define NSIG _NSIGS +#endif /* VXWORKS */ + +#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 */ + +// This one exists only to please Service_Config.h and +// Service_Manager.cpp +#if !defined (SIGHUP) +#define SIGHUP 1 +#endif /* SIGHUP */ + +#if !defined (SIGQUIT) +#define SIGQUIT 3 +#endif /* SIGQUIT */ + +#if !defined (SIGPIPE) +#define SIGPIPE 13 +#endif /* SIGPIPE */ + +#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 (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 (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 */ + +// Why is this defined? It must be a std C library symbol. +#if !defined (NSIG) +#define NSIG 1 +#endif /* NSIG */ + +#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 (EIDRM) +#define EIDRM 0 +#endif /* !EIDRM */ + +#if !defined (ENOTSUP) +#define ENOTSUP ENOSYS // Operation not supported . +#endif /* !ENOTSUP */ + +#if !defined (EDEADLK) +#define EDEADLK 1000 // Some large number.... +#endif /* !ENOTSUP */ + +#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 */ + +#define LOCALNAME 0 +#define REMOTENAME 1 + +#if defined (ACE_HAS_64BIT_LONGS) +// Necessary to support the Alphas, which have 64 bit longs and 32 bit +// ints... +typedef u_int ACE_UINT32; +#else +typedef u_long ACE_UINT32; +#endif /* ACE_HAS_64BIT_LONGS */ + +#if !defined (ETIMEDOUT) && defined (ETIME) +#define ETIMEDOUT ETIME +#endif /* ETIMEDOUT */ + +#if !defined (ETIME) && defined (ETIMEDOUT) +#define ETIME ETIMEDOUT +#endif /* ETIMED */ + +// Note that this assumes shorts are 16 bits. +typedef u_short ACE_USHORT16; + +#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) +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 */ + +// 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 void *(*ACE_THR_FUNC)(void *); +typedef const char **SYS_SIGLIST; + +#if !defined (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 */ + +#if defined (ACE_HAS_CHARPTR_DL) +typedef LPTSTR ACE_DL_TYPE; +#else +typedef LPCTSTR ACE_DL_TYPE; +#endif /* ACE_HAS_CHARPTR_DL */ + +#if !defined (ACE_HAS_SIGINFO_T) +typedef int siginfo_t; +#endif /* ACE_HAS_SIGINFO_T */ + +#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 */ + +// Type of the extended signal handler. +typedef void (*ACE_Sig_Handler_Ex) (int, siginfo_t *siginfo, ucontext_t *ucontext); + +// 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 <xti.h> +#ifdef UNIXWARE // They apparantly forgot one... +extern "C" int _xti_error(char *); +#endif /* UNIXWARE */ +#endif /* ACE_REDEFINES_XTI_FUNCTIONS */ + +class ACE_Export ACE_OS + // = TITLE + // This class defines an operating system independent + // programming API that shields developers from non-portable + // aspects of writing efficient system programs on Win32, POSIX, + // and other versions of UNIX. + // + // = DESCRIPTION + // This class encapsulates all the differences between various + // versions of UNIX and WIN32! The other components in + // ACE are programmed to use only the methods in this class, + // which makes it *much* easier to move ACE to a new platform. + // The methods in this class also automatically restart when + // interrupts occur during system calls (assuming that the + // ACE_Log_Msg::restart() flag is enabled). +{ +public: + struct flock_t + // = TITLE + // OS file locking structure. + { + void dump (void) const; + // Dump state of the object. + +#if defined (ACE_WIN32) + ACE_OVERLAPPED overlapped_; +#else + struct flock lock_; +#endif /* ACE_WIN32 */ + + ACE_HANDLE handle_; + // Handle to the underlying file. + }; + + // = A set of wrappers for miscellaneous operations. + static int atoi (const char *s); + static char *getenv (const char *symbol); + static int getopt (int argc, char *const *argv, const char *optstring); + static long sysconf (int); + + // = A set of wrappers for condition variables. + static int cond_broadcast (ACE_cond_t *cv); + static int cond_destroy (ACE_cond_t *cv); + static int cond_init (ACE_cond_t *cv, int type = USYNC_THREAD, LPCTSTR name = 0, void *arg = 0); + 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) + 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 */ + + // = A set of wrappers for determining config info. + static char *cuserid (char *user, size_t maxlen = 32); + static int uname (struct utsname *name); + static long sysinfo (int cmd, char *buf, long count); + static int hostname (char *name, size_t maxnamelen); + + // = A set of wrappers for explicit dynamic linking. + static int dlclose (void *handle); + static char *dlerror (void); + static void *dlopen (ACE_DL_TYPE filename, int mode); + static void *dlsym (void *handle, ACE_DL_TYPE symbol); + + // = A set of wrappers for stdio file operations. + static int last_error (void); + static void last_error (int); + static int fclose (FILE *fp); + static int fcntl (ACE_HANDLE handle, int cmd, int val = 0); + static int fdetach (const char *file); + static FILE *fdopen (ACE_HANDLE handle, const char *mode); + static char *fgets (char *buf, int size, FILE *fp); + static int fflush (FILE *fp); + static FILE *fopen (const char *filename, const char *mode); + static int fprintf (FILE *fp, const char *format, ...); + static size_t fread (void *ptr, size_t size, size_t nelems, FILE + *fp); + static int fstat (ACE_HANDLE, struct stat *); + static int ftruncate (ACE_HANDLE, off_t); + static size_t fwrite (const void *ptr, size_t size, size_t nitems, + FILE *fp); + static char *gets (char *str); + static void perror (const char *s); + static int printf (const char *format, ...); + static int puts (const char *s); + static void rewind (FILE *fp); + static int sprintf (char *buf, const char *format, ...); + + // = A set of wrappers for file locks. + static int flock_init (ACE_OS::flock_t *lock, int flags = 0, + LPCTSTR name = 0, mode_t perms = 0); + static int flock_destroy (ACE_OS::flock_t *lock); + static int flock_rdlock (ACE_OS::flock_t *lock, short whence = 0, + off_t start = 0, off_t len = 0); + static int flock_tryrdlock (ACE_OS::flock_t *lock, short whence = 0, + off_t start = 0, off_t len = 0); + static int flock_trywrlock (ACE_OS::flock_t *lock, short whence = 0, + off_t start = 0, off_t len = 0); + static int flock_unlock (ACE_OS::flock_t *lock, short whence = 0, + off_t start = 0, off_t len = 0); + static int flock_wrlock (ACE_OS::flock_t *lock, short whence = 0, + off_t start = 0, off_t len = 0); + + // = A set of wrappers for low-level process operations. + 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 pid_t fork (void); + static pid_t fork_exec (char *argv[]); + // 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 uid_t getgid (void); + static pid_t getpid (void); + static uid_t getuid (void); + static pid_t setsid (void); + static int system (const char *s); + static pid_t wait (int * = 0); + static pid_t waitpid (pid_t, int * = 0, int = 0); + + // = A set of wrappers for timers and resource stats. + static u_int alarm (u_int delay); + static hrtime_t gethrtime (void); + 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); + + // = A set of wrappers for operations on time. + static time_t time (time_t *tloc); + static struct tm *localtime (const time_t *clock); + static struct tm *localtime_r (const time_t *clock, struct tm *res); + static char *asctime (const struct tm *tm); + static char *ctime (const time_t *t); + static char *ctime_r (const time_t *clock, char *buf, int buflen); + static char *asctime_r (const struct tm *tm, char *buf, int buflen); + + // = A set of wrappers for memory managment. + static void *sbrk (int brk); + static void *malloc (size_t); + static void *realloc (void *, size_t); + static void free (void *); + + // = A set of wrappers for memory copying operations. + static int memcmp (const void *s, const void *t, size_t len); + static void *memcpy (void *s, const void *t, size_t len); + static void *memset (void *s, int c, size_t len); + + // = 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); + + // = 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); + 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); + + // = A set of wrappers for mutex locks. + static int mutex_init (ACE_mutex_t *m, int type = USYNC_THREAD, + LPCTSTR name = 0, void *arg = 0); + static int mutex_destroy (ACE_mutex_t *m); + static int mutex_lock (ACE_mutex_t *m); + static int mutex_trylock (ACE_mutex_t *m); + static int mutex_unlock (ACE_mutex_t *m); + + + // = 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 = USYNC_THREAD, + LPCTSTR name = 0, void *arg = 0); + static int thread_mutex_destroy (ACE_thread_mutex_t *m); + static int thread_mutex_lock (ACE_thread_mutex_t *m); + static int thread_mutex_trylock (ACE_thread_mutex_t *m); + static int thread_mutex_unlock (ACE_thread_mutex_t *m); + + // = A set of wrappers for low-level file operations. + static int access (const char *path, int amode); + static int close (ACE_HANDLE handle); + static ACE_HANDLE creat (LPCTSTR 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 int getmsg (ACE_HANDLE handle, struct strbuf *ctl, struct strbuf + *data, int *flags); + static getpmsg (ACE_HANDLE handle, struct strbuf *ctl, struct strbuf + *data, int *band, int *flags); + static int ioctl (ACE_HANDLE handle, int cmd, void * = 0); + static int isastream (ACE_HANDLE handle); + static int isatty (ACE_HANDLE handle); + static off_t lseek (ACE_HANDLE handle, off_t offset, int whence); + static ACE_HANDLE open (LPCTSTR filename, int mode, int perms = 0); + static int putmsg (ACE_HANDLE handle, const struct strbuf *ctl, const + struct strbuf *data, int flags); + static 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 *); + static ssize_t readv (ACE_HANDLE handle, struct iovec *iov, int iovlen); + static int recvmsg (ACE_HANDLE handle, struct msghdr *msg, int flags); + static int sendmsg (ACE_HANDLE handle, ACE_SENDMSG_TYPE *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 *); + static int writev (ACE_HANDLE handle, ACE_WRITEV_TYPE *iov, int iovcnt); + + // = A set of wrappers for event demultiplexing and IPC. + static int select (int width, fd_set *rfds, fd_set *wfds, fd_set *efds, 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, 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[]); + + // = A set of wrappers for directory operations. + static int chdir (const char *path); + static int mkfifo (const char *file, mode_t mode); + static char *mktemp (char *t); + static char *getcwd (char *, size_t); + static mode_t umask (mode_t cmask); + static int unlink (const char *path); + + // = 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); + + // = A set of wrappers for readers/writer locks. + static int rwlock_init (ACE_rwlock_t *rw, int type = USYNC_THREAD, + LPCTSTR name = 0, void *arg = 0); + static int rwlock_destroy (ACE_rwlock_t *rw); + static int rw_rdlock (ACE_rwlock_t *rw); + static int rw_tryrdlock (ACE_rwlock_t *rw); + static int rw_trywrlock (ACE_rwlock_t *rw); + static int rw_unlock (ACE_rwlock_t *rw); + static int rw_wrlock (ACE_rwlock_t *rw); + + // = A set of wrappers for auto-reset and manuaevents. + static int event_init (ACE_event_t *event, + int manual_reset = 0, + int initial_state = 0, + int type = USYNC_THREAD, + LPCTSTR name = 0, + void *arg = 0); + 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); + static int event_signal (ACE_event_t *event); + static int event_pulse (ACE_event_t *event); + static int event_reset (ACE_event_t *event); + + // = 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 = USYNC_THREAD, + LPCTSTR name = 0, void *arg = 0, + int max = 0x7fffffff); + static int sema_post (ACE_sema_t *s); + static int sema_trywait (ACE_sema_t *s); + static int sema_wait (ACE_sema_t *s); + + // = 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); + + // = 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); + + // = 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 sigprocmask (int how, const sigset_t *nsp, sigset_t *osp); + + // = A set of wrappers for sockets. + static ACE_HANDLE accept (ACE_HANDLE handle, struct sockaddr *addr, + int *addrlen); + static int bind (ACE_HANDLE s, struct sockaddr *name, int namelen); + static int connect (ACE_HANDLE handle, struct sockaddr *addr, int + addrlen); + 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 *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 long inet_addr (const char *name); + static char *inet_ntoa (const struct in_addr addr); + 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 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 setsockopt (ACE_HANDLE handle, int level, int optname, + const char *optval, int optlen); + static int shutdown (ACE_HANDLE handle, int how); + static ACE_HANDLE socket (int domain, int type, int proto); + static int socketpair (int domain, int type, int protocol, + ACE_HANDLE sv[2]); + static int socket_init (int version_high = 1, int version_low = 1); + // Initialize WinSock before first use (e.g., when a DLL is first + // loaded or the first use of a socket() call. + + static int socket_fini (void); + // Finialize WinSock after last use (e.g., when a DLL is unloaded). + + // = 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); + + // = A set of wrappers for non-UNICODE string operations. + static int strcasecmp (const char *s, const char *t); + static char *strcat (char *s, const char *t); + static char *strchr (const char *s, int c); + static char *strrchr (const char *s, int c); + static int strcmp (const char *s, const char *t); + static char *strcpy (char *s, const char *t); + static size_t strspn(const char *s1, const char *s2); + static char *strstr (const char *s, const char *t); + static char *strdup (const char *s); + static size_t strlen (const char *s); + static int strncmp (const char *s, const char *t, size_t len); + static char *strncpy (char *s, const char *t, size_t len); + static char *strtok (char *s, const char *tokens); + static char *strtok_r (char *s, const char *tokens, char **lasts); + static long strtol (const char *s, char **ptr, int base); + +#if defined (ACE_HAS_UNICODE) + // = A set of wrappers for non-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); + static int strcmp (const wchar_t *s, const wchar_t *t); + static wchar_t *strcpy (wchar_t *s, const wchar_t *t); +// static wchar_t *strstr (const wchar_t *s, const wchar_t *t); +// static wchar_t *strdup (const wchar_t *s); + static size_t strlen (const wchar_t *s); + static int strncmp (const wchar_t *s, const wchar_t *t, size_t len); + static wchar_t *strncpy (wchar_t *s, const wchar_t *t, size_t len); + static wchar_t *strtok (wchar_t *s, const wchar_t *tokens); + static long strtol (const wchar_t *s, wchar_t **ptr, int base); +#endif /* ACE_HAS_UNICODE */ + + // = A set of wrappers for TLI. + static int t_accept (ACE_HANDLE fildes, int 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(int fildes, struct t_call *sndcall, + struct t_call *rcvcall); + static void t_error (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 int 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 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, char *buf, unsigned 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); + + // = A set of wrappers for threads. + static int thr_continue (ACE_hthread_t target_thread); + static int thr_create (ACE_THR_FUNC, + void *args, + long flags, + ACE_thread_t *thr_id, + ACE_hthread_t *t_handle = 0, + u_int priority = 0, + void *stack = 0, + size_t stacksize = 0); + 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 thr_getprio (ACE_hthread_t thr_id, int *prio); + static int thr_getspecific (ACE_thread_key_t key, void **data); + 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_keyfree (ACE_thread_key_t key); + static int thr_key_detach (void *inst); + 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); + static size_t thr_min_stack (void); + static ACE_thread_t thr_self (void); + static void thr_self (ACE_hthread_t &); + static int thr_setconcurrency (int hint); + static int thr_setprio (ACE_hthread_t thr_id, int prio); + 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_suspend (ACE_hthread_t target_thread); + static int thr_setcancelstate (int new_state, int *old_state); + static int thr_setcanceltype (int new_type, int *old_type); + static int thr_cancel (ACE_thread_t t_id); + static int sigwait (sigset_t *set, int *sig = 0); + static void thr_testcancel (void); + static void thr_yield (void); + + static ACE_thread_t NULL_thread; + // This is necessary to deal with POSIX pthreads insanity... + +#if defined (ACE_WIN32) + static int socket_initialized_; + // Keeps track of whether we've already initialized WinSock... +#endif /* ACE_WIN32 */ + +private: + ACE_OS (void); + // Ensure we can't define an instance of this class. + + static void mutex_lock_cleanup (void *lock); +}; + +#include "ace/Trace.h" + +#if defined (ACE_HAS_INLINED_OSCALLS) +#if defined (ACE_INLINE) +#undef ACE_INLINE +#endif /* ACE_INLINE */ +#define ACE_INLINE inline +#include "ace/OS.i" +#endif /* ACE_HAS_INLINED_OSCALLS */ + +#endif /* ACE_OS_H */ diff --git a/ace/OS.i b/ace/OS.i new file mode 100644 index 00000000000..2fcbad1847f --- /dev/null +++ b/ace/OS.i @@ -0,0 +1,5297 @@ +/* -*- C++ -*- */ +// $Id$ + +#if !defined (ACE_HAS_INLINED_OSCALLS) +#undef ACE_INLINE +#define ACE_INLINE +#endif /* ACE_HAS_INLINED_OSCALLS */ + +#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 sis_siglist +#endif /* !defined (sys_siglist) */ +extern char **_sys_siglist; +#endif /* !ACE_HAS_SYS_SIGLIST */ + +#if 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_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 (ACE_NEEDS_WRITEV) +extern "C" int writev (ACE_HANDLE handle, ACE_WRITEV_TYPE *iov, int iovcnt); +#endif /* ACE_NEEDS_WRITEV */ + +#if defined (ACE_NEEDS_READV) +extern "C" ssize_t readv (ACE_HANDLE handle, struct iovec *iov, int iovcnt); +#endif /* ACE_NEEDS_READV */ + +#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 <xliuser.h> +#endif /* ACE_HAS_XLI */ + +#if !defined (ACE_HAS_CPLUSPLUS_HEADERS) +#include <libc.h> +#include <osfcn.h> +#endif /* ACE_HAS_CPLUSPLUS_HEADERS */ + +#if defined (ACE_HAS_SYSENT_H) +#include <sysent.h> +#endif /* ACE_HAS_SYSENT_H_*/ + +#if defined (ACE_HAS_SYS_FILIO_H) +#include <sys/filio.h> +#endif /* ACE_HAS_SYS_FILIO_H */ + +#if defined (ACE_HAS_SVR4_GETTIMEOFDAY) +#if !defined (m88k) +extern "C" int gettimeofday (struct timeval *tp, void * = 0); +#else +extern "C" int gettimeofday (struct timeval *tp); +#endif // m88k +#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 +/* +#elif defined (ACE_HAS_IRIX_GETTIMEOFDAY) +extern "C" int gettimeofday (struct timeval *tp, ...); +#else +extern "C" int gettimeofday (struct timeval *tp); +*/ +#endif /* ACE_HAS_SVR4_GETTIMEOFDAY */ + +#if !defined (ACE_LACKS_MALLOC_H) +#include <malloc.h> +#endif /* ACE_LACKS_MALLOC_H */ + +#if !defined (ACE_WIN32) + +#if !defined (ACE_LACKS_RPC_H) +#include <rpc/rpc.h> +#endif /* ACE_LACKS_RPC_H */ + + +// Matthew Stevens 7-10-95 Fix GNU GCC 2.7 for memchr() problem. +#if !defined (ACE_HAS_GNU_CSTRING_H) + +#if defined (VXWORKS) +#include <string.h> +#else +#include <memory.h> +#endif /* VXWORKS */ +#endif /* ACE_HAS_GNU_CSTRING_H */ + +// These prototypes are chronically lacking from many versions of +// UNIX. +extern "C" int t_getname (int, struct netbuf *, int); +extern "C" int isastream (int); +extern "C" int getrusage (int who, struct rusage *rusage); + +#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 <regexpr.h> +#endif /* ACE_HAS_REGEX */ + +#if defined (ACE_HAS_SYSINFO) +#include <sys/systeminfo.h> +#endif /* ACE_HAS_SYS_INFO */ + +#if defined (ACE_HAS_SYSCALL_H) +#include <sys/syscall.h> +#endif /* ACE_HAS_SYSCALL_H */ + +#if defined (UNIXWARE) // See strcasecmp, below +#include <ctype.h> +#endif /* UNIXWARE */ + +// Adapt the weird threading and synchronization routines (which don't +// return -1 normally) so that they return -1 and work correctly with +// 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 */ + +#if defined (SIGNAL_SAFE_OS_CALLS) +#include "ace/Log_Msg.h" +// The following two macros ensure that system calls are properly +// restarted (if necessary) when interrupts occur. +#define ACE_OSCALL(OP,TYPE,FAILVALUE,RESULT) \ + do \ + RESULT = (TYPE) OP; \ + while (RESULT == FAILVALUE && errno == EINTR && ACE_LOG_MSG->restart ()) +#define ACE_OSCALL_RETURN(OP,TYPE,FAILVALUE) \ + do { \ + TYPE _result; \ + do \ + _result = (TYPE) OP; \ + while (_result == FAILVALUE && errno == EINTR && ACE_LOG_MSG->restart ()); \ + return _result; \ + } while (0) +#else +#define ACE_OSCALL_RETURN(OP,TYPE,FAILVALUE) do { TYPE _result; return OP; } while (0) +#define ACE_OSCALL(OP,TYPE,FAILVALUE,RESULT) do { RESULT = (TYPE) OP; } while (0) +#endif /* SIGNAL_SAFE_OS_CALLS */ + +ACE_INLINE int +ACE_OS::chdir (const char *path) +{ +// ACE_TRACE ("ACE_OS::chdir"); +#if defined (VXWORKS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::chdir ((char *) path), _result), + int, ERROR); +#else + ACE_OSCALL_RETURN (::chdir (path), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::fcntl (ACE_HANDLE handle, int cmd, int value) +{ +// ACE_TRACE ("ACE_OS::fcntl"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::fcntl (handle, cmd, value), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::fstat (ACE_HANDLE handle, struct stat *stp) +{ +// ACE_TRACE ("ACE_OS::fstat"); + ACE_OSCALL_RETURN (::fstat (handle, stp), int, -1); +} + +ACE_INLINE uid_t +ACE_OS::getgid (void) +{ +// ACE_TRACE ("ACE_OS::getgid"); +#if defined (VXWORKS) + // getgid() is not supported: just one group anyways + return 0; +#else + ACE_OSCALL_RETURN (::getgid (), uid_t, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::getopt (int argc, char *const *argv, const char *optstring) +{ +// ACE_TRACE ("ACE_OS::getopt"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::getopt (argc, (const char* const *) argv, optstring), int, -1); +#else + ACE_OSCALL_RETURN (::getopt (argc, argv, optstring), int, -1); +#endif /* ACE_LACKS_POSIX_PROTO */ +} + +ACE_INLINE uid_t +ACE_OS::getuid (void) +{ +// ACE_TRACE ("ACE_OS::getuid"); +#if defined (VXWORKS) + // getuid() is not supported: just one user anyways + return 0; +#else + ACE_OSCALL_RETURN (::getuid (), uid_t, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::isatty (ACE_HANDLE fd) +{ +// ACE_TRACE ("ACE_OS::isatty"); + ACE_OSCALL_RETURN (::isatty (fd), int, -1); +} + +ACE_INLINE int +ACE_OS::mkfifo (const char *file, mode_t mode) +{ +// ACE_TRACE ("ACE_OS::mkfifo"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::mkfifo (file, mode), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::pipe (ACE_HANDLE fds[]) +{ +// ACE_TRACE ("ACE_OS::pipe"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::pipe (fds), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::rand_r (ACE_RANDR_TYPE seed) +{ +// ACE_TRACE ("ACE_OS::rand_r"); +#if defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) + ACE_OSCALL_RETURN (::rand_r (seed), int, -1); +#else + ACE_OSCALL_RETURN (::rand (), int, -1); +#endif +} + +ACE_INLINE void * +ACE_OS::sbrk (int brk) +{ +// ACE_TRACE ("ACE_OS::sbrk"); + +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#else + ACE_OSCALL_RETURN (::sbrk (brk), void *, 0); +#endif /* VXWORKS */ +} + +ACE_INLINE pid_t +ACE_OS::setsid (void) +{ +// ACE_TRACE ("ACE_OS::setsid"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::setsid (), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::sigaddset (sigset_t *s, int signum) +{ +// ACE_TRACE ("ACE_OS::sigaddset"); + ACE_OSCALL_RETURN (::sigaddset (s, signum), int, -1); +} + +ACE_INLINE int +ACE_OS::sigdelset (sigset_t *s, int signum) +{ +// ACE_TRACE ("ACE_OS::sigdelset"); + ACE_OSCALL_RETURN (::sigdelset (s, signum), int, -1); +} + +ACE_INLINE int +ACE_OS::sigemptyset (sigset_t *s) +{ +// ACE_TRACE ("ACE_OS::sigemptyset"); + ACE_OSCALL_RETURN (::sigemptyset (s), int, -1); +} + +ACE_INLINE int +ACE_OS::sigfillset (sigset_t *s) +{ +// ACE_TRACE ("ACE_OS::sigfillset"); + ACE_OSCALL_RETURN (::sigfillset (s), int, -1); +} + +ACE_INLINE int +ACE_OS::sigismember (sigset_t *s, int signum) +{ +// ACE_TRACE ("ACE_OS::sigismember"); + ACE_OSCALL_RETURN (::sigismember (s, signum), int, -1); +} + +ACE_INLINE int +ACE_OS::sigprocmask (int how, const sigset_t *nsp, sigset_t *osp) +{ +// ACE_TRACE ("ACE_OS::sigprocmask"); +#if defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::sigprocmask (how, (int*) nsp, osp), int, -1); +#else + ACE_OSCALL_RETURN (::sigprocmask (how, nsp, osp), int, -1); +#endif /* ACE_LACKS_POSIX_PROTO */ +} + +ACE_INLINE int +ACE_OS::strcasecmp (const char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strcasecmp"); +#if defined (UNIXWARE) || defined (VXWORKS) + + // Handles most of what the BSD version does, but does not indicate + // lexicographic ordering if the strings are unequal. Just + // indicates equal (ignoring case) by return value == 0, else not + // equal. + int result = 0; + + while (*s != '\0' && *t != '\0') + { + if (tolower (*s) != tolower (*t)) + { + result = 1; + break; + } + ++s; ++t; + } + + return result; // == 0 for match, else 1 +#else + return ::strcasecmp (s, t); +#endif /* UNIXWARE || VXWORKS */ +} + +ACE_INLINE mode_t +ACE_OS::umask (mode_t cmask) +{ +// ACE_TRACE ("ACE_OS::umask"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::umask (cmask), mode_t, -1); +#endif /* VXWORKS */ +} + +#else // ACE_WIN32 + +// This is for Win32 exclusively! + +// 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 (errno = ::GetLastError ()) { \ + case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; \ + } \ + return RESULT; } while (0) +#define ACE_OSCALL_RETURN(X,TYPE,FAILVALUE) \ + do { \ + TYPE _result = (TYPE) X; \ + if (_result == FAILVALUE) \ + errno = ::GetLastError (); \ + return _result; \ + } while (0) +#define ACE_OSCALL(X,TYPE,FAILVALUE,RESULT) \ + do { \ + RESULT = (TYPE) X; \ + if (RESULT == FAILVALUE) \ + errno = ::GetLastError (); \ + } while (0) + +ACE_INLINE int +ACE_OS::chdir (const char *path) +{ +// ACE_TRACE ("ACE_OS::chdir"); + ACE_OSCALL_RETURN (::_chdir (path), int, -1); +} + +ACE_INLINE int +ACE_OS::strcasecmp (const char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strcasecmp"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::fcntl (ACE_HANDLE handle, int cmd, int value) +{ +// ACE_TRACE ("ACE_OS::fcntl"); + ACE_NOTSUP_RETURN (0); // We should be able to map this stuff +} + +ACE_INLINE uid_t +ACE_OS::getgid (void) +{ +// ACE_TRACE ("ACE_OS::getgid"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE int +ACE_OS::getopt (int argc, char *const *argv, const char *optstring) +{ +// ACE_TRACE ("ACE_OS::getopt"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE uid_t +ACE_OS::getuid (void) +{ +// ACE_TRACE ("ACE_OS::getuid"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE int +ACE_OS::isatty (ACE_HANDLE fd) +{ +// ACE_TRACE ("ACE_OS::isatty"); + ACE_NOTSUP_RETURN (-1); +// ACE_OSCALL_RETURN (::_isatty (fd), int, -1); +} + +ACE_INLINE int +ACE_OS::mkfifo (const char *file, mode_t mode) +{ +// ACE_TRACE ("ACE_OS::mkfifo"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE int +ACE_OS::pipe (ACE_HANDLE fds[]) +{ +// ACE_TRACE ("ACE_OS::pipe"); + ACE_NOTSUP_RETURN (-1); +// ACE_OSCALL_RETURN (::_pipe (fds, PIPE_BUF, 0), int, -1); // Use default mode +} + +ACE_INLINE int +ACE_OS::rand_r (ACE_RANDR_TYPE seed) +{ +// ACE_TRACE ("ACE_OS::rand_r"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE void * +ACE_OS::sbrk (int brk) +{ +// ACE_TRACE ("ACE_OS::sbrk"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE pid_t +ACE_OS::setsid (void) +{ +// ACE_TRACE ("ACE_OS::setsid"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::sigaddset (sigset_t *s, int signum) +{ +// ACE_TRACE ("ACE_OS::sigaddset"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::sigdelset (sigset_t *s, int signum) +{ +// ACE_TRACE ("ACE_OS::sigdelset"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::sigemptyset (sigset_t *s) +{ +// ACE_TRACE ("ACE_OS::sigemptyset"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::sigfillset (sigset_t *s) +{ +// ACE_TRACE ("ACE_OS::sigfillset"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::sigismember (sigset_t *s, int signum) +{ +// ACE_TRACE ("ACE_OS::sigismember"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE int +ACE_OS::sigprocmask (int how, const sigset_t *nsp, sigset_t *osp) +{ +// ACE_TRACE ("ACE_OS::sigprocmask"); + ACE_NOTSUP_RETURN (0); +} + +ACE_INLINE mode_t +ACE_OS::umask (mode_t cmask) +{ +// ACE_TRACE ("ACE_OS::umask"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE int +ACE_OS::fstat (ACE_HANDLE handle, struct stat *stp) +{ +// ACE_TRACE ("ACE_OS::fstat"); + ACE_NOTSUP_RETURN (-1); +} + +#endif /* WIN32 */ + +ACE_INLINE time_t +ACE_OS::time (time_t *tloc) +{ +// ACE_TRACE ("ACE_OS::time"); + ACE_OSCALL_RETURN (::time (tloc), time_t, (time_t) -1); +} + +ACE_INLINE void +ACE_OS::srand (u_int seed) +{ +// ACE_TRACE ("ACE_OS::srand"); + ::srand (seed); +} + +ACE_INLINE int +ACE_OS::rand (void) +{ +// ACE_TRACE ("ACE_OS::rand"); + ACE_OSCALL_RETURN (::rand (), int, -1); +} + +ACE_INLINE int +ACE_OS::unlink (const char *path) +{ +// ACE_TRACE ("ACE_OS::unlink"); +#if defined (VXWORKS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::unlink ((char *) path), _result), + int, ERROR); +#else + ACE_OSCALL_RETURN (::unlink (path), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE char * +ACE_OS::cuserid (char *user, size_t maxlen) +{ +// ACE_TRACE ("ACE_OS::cuserid"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) + // Hackish because of missing buffer size! + return ::GetUserName (user, (unsigned long *) &maxlen) ? user : 0; +#else + ACE_OSCALL_RETURN (::cuserid (user), char *, 0); +#endif /* VXWORKS */ +} + +// Doesn't need a macro since it *never* returns! + +ACE_INLINE void +ACE_OS::_exit (int status) +{ +// ACE_TRACE ("ACE_OS::_exit"); +#if defined (VXWORKS) + ::exit (status); +#else + ::_exit (status); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::memcmp (const void *s, const void *t, size_t len) +{ +// ACE_TRACE ("ACE_OS::memcmp"); + return ::memcmp (s, t, len); +} + +ACE_INLINE void * +ACE_OS::memcpy (void *s, const void *t, size_t len) +{ +// ACE_TRACE ("ACE_OS::memcpy"); + return ::memcpy (s, t, len); +} + +ACE_INLINE void * +ACE_OS::memset (void *s, int c, size_t len) +{ +// ACE_TRACE ("ACE_OS::memset"); + return ::memset (s, c, len); +} + +ACE_INLINE long +ACE_OS::sysconf (int name) +{ +// ACE_TRACE ("ACE_OS::sysconf"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::sysconf (name), long, -1); +#endif /* ACE_WIN32 || VXWORKS */ +} + +ACE_INLINE int +ACE_OS::mutex_init (ACE_mutex_t *m, + int type, + LPCTSTR name, + void *arg) +{ +// ACE_TRACE ("ACE_OS::mutex_init"); + +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined(ACE_HAS_PTHREADS) + pthread_mutexattr_t attributes; + int result = -1; + +#if defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_PTHREAD_ATTR_INIT) + if (::pthread_mutexattr_init (&attributes) == 0 + && ::pthread_mutexattr_setkind_np (&attributes, type) == 0 + && ::pthread_mutex_init (m, &attributes) == 0) +#else + if (::pthread_mutexattr_create (&attributes) == 0 + && ::pthread_mutexattr_setkind_np (&attributes, type) == 0 + && ::pthread_mutex_init (m, attributes) == 0) +#endif /* ACE_HAS_PTHREAD_ATTR_INIT */ +#else + if (::pthread_mutexattr_init (&attributes) == 0 + && ::pthread_mutex_init (m, &attributes) == 0) +#endif /* ACE_HAS_SETKIND_NP */ + result = 0; + +#if defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_PTHREAD_ATTR_DESTROY) + ::pthread_mutexattr_destroy (&attributes); +#else + ::pthread_mutexattr_delete (&attributes); +#endif /* ACE_HAS_PTHREAD_ATTR_DESTROY */ +#else + ::pthread_mutexattr_destroy (&attributes); +#endif /* ACE_HAS_SETKIND_NP */ + + return result; +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m, type, arg), + _result), + int, -1); +#elif defined (ACE_HAS_WTHREADS) + m->type_ = type; + + switch (type) + { + case USYNC_PROCESS: + m->proc_mutex_ = ::CreateMutex (NULL, 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, arg); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#elif defined (VXWORKS) + // Type includes these options: SEM_Q_PRIORITY, SEM_Q_FIFO, SEM_DELETE_SAFE, + // and SEM_INVERSION_SAFE that are currently outside of the ACE mutex model. + return (*m = ::semMCreate (type)) == NULL ? -1 : 0; +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::mutex_destroy (ACE_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::mutex_destroy"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m), _result), int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_), + _result), + int, -1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_destroy (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#elif defined (VXWORKS) + return ::semDelete (*m) == OK ? 0 : -1; +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::mutex_lock (ACE_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::mutex_lock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_lock (m), _result), int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + // Timeout can't occur, so don't bother checking... + if (::WaitForSingleObject(m->proc_mutex_, INFINITE) == WAIT_OBJECT_0) + return 0; + else + // This is a hack, we need to find an appropriate mapping... + ACE_FAIL_RETURN (-1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_lock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#elif defined (VXWORKS) + return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1; +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::mutex_trylock (ACE_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::mutex_trylock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_trylock (m), _result), int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + { + // Try for 0 milliseconds - i.e. nonblocking. + DWORD result = ::WaitForSingleObject(m->proc_mutex_, 0); + + if (result == WAIT_OBJECT_0) + return 0; + else + { + errno = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); + // This is a hack, we need to find an appropriate mapping... + return -1; + } + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_trylock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#elif defined (VXWORKS) + if ( ::semTake (*m, NO_WAIT) == ERROR ) + if ( errno == S_objLib_OBJ_TIMEOUT ) + // couldn't get the semaphore + return 1; + else + // error + return -1; + else + // got the semaphore + return 0; +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::mutex_unlock (ACE_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::mutex_unlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_unlock (m), _result), int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_), + _result), + int, -1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_unlock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#elif defined (VXWORKS) + return ::semGive (*m) == OK ? 0 : -1; +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m, + int type, + LPCTSTR name, + void *arg) +{ + // ACE_TRACE ("ACE_OS::thread_mutex_init"); + +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + // Force the use of USYNC_THREAD! + return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg); +#elif defined (ACE_HAS_WTHREADS) + ::InitializeCriticalSection (m); + return 0; +#elif defined (VXWORKS) + return mutex_init (m, type, name, arg); +#endif /* ACE_HAS_STHREADS || ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_destroy (ACE_thread_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::thread_mutex_destroy"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + return ACE_OS::mutex_destroy (m); +#elif defined (ACE_HAS_WTHREADS) + ::DeleteCriticalSection (m); + return 0; +#elif defined (VXWORKS) + return mutex_destroy (m); +#endif /* ACE_HAS_STHREADS || ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::thread_mutex_lock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + return ACE_OS::mutex_lock (m); +#elif defined (ACE_HAS_WTHREADS) + ::EnterCriticalSection (m); + return 0; +#elif defined (VXWORKS) + return mutex_lock (m); +#endif /* ACE_HAS_STHREADS || ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_trylock (ACE_thread_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::thread_mutex_trylock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + return ACE_OS::mutex_trylock (m); +#elif defined (ACE_HAS_WTHREADS) +#if defined (ACE_HAS_WIN32_TRYLOCK) + ::TryEnterCriticalSection (m); + return 0; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_WIN32_TRYLOCK */ +#elif defined (VXWORKS) + return mutex_trylock (m); +#endif /* ACE_HAS_STHREADS || ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_unlock (ACE_thread_mutex_t *m) +{ +// ACE_TRACE ("ACE_OS::thread_mutex_unlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + return ACE_OS::mutex_unlock (m); +#elif defined (ACE_HAS_WTHREADS) + ::LeaveCriticalSection (m); + return 0; +#elif defined (VXWORKS) + return mutex_unlock (m); +#endif /* ACE_HAS_STHREADS || ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_broadcast (ACE_cond_t *cv) +{ +// ACE_TRACE ("ACE_OS::cond_broadcast"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_broadcast (cv), + _result), + int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_broadcast (cv), + _result), + int, -1); +#elif defined (ACE_HAS_WTHREADS) || defined (VXWORKS) + int result = 0; + int error = 0; + + for (int i = cv->waiters_; i > 0; i--) + if (ACE_OS::sema_post (&cv->sema_) != 0) + { + error = errno; + result = -1; + break; + } + + errno = error; + return result; +#endif /* ACE_HAS_STHREADS */ +#else + cv = cv; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_destroy (ACE_cond_t *cv) +{ +// ACE_TRACE ("ACE_OS::cond_destroy"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_destroy (cv), _result), int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_destroy (cv), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) || defined (VXWORKS) + return ACE_OS::sema_destroy (&cv->sema_); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_init (ACE_cond_t *cv, int type, LPCTSTR name, void *arg) +{ +// ACE_TRACE ("ACE_OS::cond_init"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + pthread_condattr_t attributes; + int result = -1; + +#if defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_PTHREAD_ATTR_INIT) + if (::pthread_condattr_init (&attributes) == 0 + && ::pthread_cond_init (cv, &attributes) == 0 +#else + if (::pthread_condattr_create (&attributes) == 0 + && ::pthread_cond_init (cv, attributes) == 0 +#endif /* ACE_HAS_PTHREAD_ATTR_INIT */ +#else + if (::pthread_condattr_init (&attributes) == 0 + && ::pthread_cond_init (cv, &attributes) == 0 +#endif /* ACE_HAS_SETKIND_NP */ +#if !defined (ACE_LACKS_CONDATTR_PSHARED) + && ::pthread_condattr_setpshared (&attributes, type) == 0 +#endif /* ACE_LACKS_CONDATTR_PSHARED */ + ) + result = 0; + +#if defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_PTHREAD_ATTR_DESTROY) + ::pthread_condattr_destroy (&attributes); +#else + ::pthread_condattr_delete (&attributes); +#endif /* ACE_HAS_PTHREAD_ATTR_DESTROY */ +#else + ::pthread_condattr_destroy (&attributes); +#endif /* ACE_HAS_SETKIND_NP */ + + return result; +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_init (cv, type, arg), + _result), + int, -1); +#elif defined (ACE_HAS_WTHREADS) || defined (VXWORKS) + cv->waiters_ = 0; + + return ACE_OS::sema_init (&cv->sema_, 0, type, name, arg); +#endif /* ACE_HAS_STHREADS */ +#else + cv = cv; + type = type; + name = name; + arg = arg; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_signal (ACE_cond_t *cv) +{ +// ACE_TRACE ("ACE_OS::cond_signal"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_signal (cv), _result), int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_signal (cv), _result), int, -1); +#elif defined (ACE_HAS_WTHREADS) || defined (VXWORKS) + // If there aren't any waiters, then this is a no-op. Note that + // this function *must* be called with the <external_mutex> held + // since other wise there is a race condition that can lead to the + // lost wakeup bug... + if (cv->waiters_ > 0) + return ACE_OS::sema_post (&cv->sema_); + else + return 0; +#endif /* ACE_HAS_STHREADS */ +#else + cv = cv; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_timedwait (ACE_cond_t *cv, + ACE_mutex_t *external_mutex, + ACE_Time_Value *timeout) +{ +// ACE_TRACE ("ACE_OS::cond_timedwait"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_WTHREADS) + // Note that it is ok to increment this because the <external_mutex> + // is locked! + cv->waiters_++; + + if (ACE_OS::mutex_unlock (external_mutex) != 0) + return -1; + + DWORD result; + + if (timeout == 0) + // Wait forever. + result = ::WaitForSingleObject (cv->sema_, INFINITE); + else if (timeout->sec () == 0 && timeout->usec () == 0) + // Do a "poll". + result = ::WaitForSingleObject (cv->sema_, 0); + else + { + // Wait for upto <relative_time> 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). + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + result = ::WaitForSingleObject (cv->sema_, relative_time.msec ()); + } + + ACE_OS::mutex_lock (external_mutex); + + cv->waiters_--; + + if (result == WAIT_OBJECT_0) + return 0; + else + { + errno = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); + // This is a hack, we need to find an appropriate mapping... + return -1; + } + +#elif defined (VXWORKS) + // POSIX semaphores don't have a timed wait. Should implement conds with + // VxWorks semaphores instead, they do have a timed wait. But all of the + // other cond operations would have to be modified. + ACE_NOTSUP_RETURN (-1); + +#else /* PTHREADS or STHREADS or DCETHREADS */ + int result; + timestruc_t ts = *timeout; // Calls ACE_Time_Value::operator timestruc_t(). +#if (defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)) && !defined (ACE_HAS_FSU_PTHREADS) + ACE_OSCALL (ACE_ADAPT_RETVAL ((timeout == 0 + ? ::pthread_cond_wait (cv, external_mutex) + : ::pthread_cond_timedwait (cv, external_mutex, +#if defined (HPUX) // They forgot a const in the system prototype... + (struct timespec *) &ts)), +#else + (const struct timespec *) &ts)), +#endif /* HPUX */ + result), + int, -1, result); + // We need to adjust this to make the POSIX and Solaris return + // values consistent. + if (result == -1 && errno == ETIMEDOUT) + errno = ETIME; +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL (ACE_ADAPT_RETVAL ((timeout == 0 + ? ::cond_wait (cv, external_mutex) + : ::cond_timedwait (cv, external_mutex, &ts)), result), + int, -1, result); +#endif /* ACE_HAS_STHREADS */ + timeout->set (ts); // Update the time value before returning. + return result; +#endif /* ACE_HAS_WTHREADS */ +#else + cv = cv; + external_mutex = external_mutex; + timeout = timeout; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_wait (ACE_cond_t *cv, + ACE_mutex_t *external_mutex) +{ +// ACE_TRACE ("ACE_OS::cond_wait"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_wait (cv, external_mutex), _result), + int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_wait (cv, external_mutex), _result), + int, -1); +#elif defined (ACE_HAS_WTHREADS) || defined (VXWORKS) + // Note that it is ok to increment this because the <external_mutex> + // is locked. + cv->waiters_++; + + if (ACE_OS::mutex_unlock (external_mutex) != 0) + return -1; + + int result = 0; + int error = 0; + + if (ACE_OS::sema_wait (&cv->sema_) != 0) + { + result = -1; + error = errno; + } + + // We must always regain the mutex, even when errors occur so that + // we can atomically decrement the count of the waiters. + ACE_OS::mutex_lock (external_mutex); + + // By making the waiter responsible for decrementing its count we + // don't have to worry about having an internal mutex. Thanks to + // Karlheinz for recognizing this optimization. + cv->waiters_--; + + // Reset errno in case mutex_lock() also fails... + errno = error; + return result; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +#if defined (ACE_WIN32) +ACE_INLINE int +ACE_OS::cond_timedwait (ACE_cond_t *cv, + ACE_thread_mutex_t *external_mutex, + ACE_Time_Value *timeout) +{ +// ACE_TRACE ("ACE_OS::cond_timedwait"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_WTHREADS) + cv->waiters_++; + + if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) + return -1; + + DWORD result; + + if (timeout == 0) + // Wait forever. + result = ::WaitForSingleObject (cv->sema_, INFINITE); + else if (timeout->sec () == 0 && timeout->usec () == 0) + // Do a "poll". + result = ::WaitForSingleObject (cv->sema_, 0); + else + { + // Wait for upto <relative_time> 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). + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + result = ::WaitForSingleObject (cv->sema_, relative_time.msec ()); + } + + ACE_OS::thread_mutex_lock (external_mutex); + + cv->waiters_--; + + if (result == WAIT_OBJECT_0) + return 0; + else + { + errno = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); + // This is a hack, we need to find an appropriate mapping... + return -1; + } +#endif /* ACE_HAS_WTHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::cond_wait (ACE_cond_t *cv, + ACE_thread_mutex_t *external_mutex) +{ +// ACE_TRACE ("ACE_OS::cond_wait"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_WTHREADS) + cv->waiters_++; + + if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) + return -1; + + int result = 0; + int error = 0; + + if (ACE_OS::sema_wait (&cv->sema_) != 0) + { + result = -1; + error = errno; + } + + // We must always regain the mutex, even when errors occur. + ACE_OS::thread_mutex_lock (external_mutex); + + cv->waiters_--; + + // Reset errno in case mutex_lock() also fails... + errno = error; + return result; + +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} +#endif /* ACE_WIN32 */ + +ACE_INLINE int +ACE_OS::rw_rdlock (ACE_rwlock_t *rw) +{ +// ACE_TRACE ("ACE_OS::rw_rdlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_rdlock (rw), _result), int, -1); +#else // NT, POSIX, and VxWorks don't support this natively. +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + pthread_cleanup_push (ACE_OS::mutex_lock_cleanup, (void *) &rw->lock_); +#endif /* ACE_HAS_DCETHREADS */ + 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_DCETHREADS) || defined (ACE_HAS_PTHREADS) + pthread_cleanup_pop (0); +#endif + return 0; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_tryrdlock (ACE_rwlock_t *rw) +{ +// ACE_TRACE ("ACE_OS::rw_tryrdlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_tryrdlock (rw), _result), int, -1); +#else // NT, POSIX, and VxWorks don't support this natively. + int result = -1; + + if (ACE_OS::mutex_lock (&rw->lock_) != -1) + { + int error = 0; + + 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_); + errno = error; + } + return result; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_trywrlock (ACE_rwlock_t *rw) +{ +// ACE_TRACE ("ACE_OS::rw_trywrlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_trywrlock (rw), _result), int, -1); +#else // NT, POSIX, and VxWorks don't support this natively. + int result = -1; + + if (ACE_OS::mutex_lock (&rw->lock_) != -1) + { + int error = 0; + + if (rw->ref_count_ != 0) + { + error = EBUSY; + result = -1; + } + else + { + rw->ref_count_ = -1; + result = 0; + } + + ACE_OS::mutex_unlock (&rw->lock_); + errno = error; + } + return result; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_unlock (ACE_rwlock_t *rw) +{ +// ACE_TRACE ("ACE_OS::rw_unlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_unlock (rw), _result), int, -1); +#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 + assert (!"count should not be 0!\n"); + + int result; + int error = 0; + + // Give preference to writers over readers... + if (rw->num_waiting_writers_ > 0) + { + result = ACE_OS::cond_signal (&rw->waiting_writers_); + error = errno; + } + else if (rw->num_waiting_readers_ > 0) + { + result = ACE_OS::cond_broadcast (&rw->waiting_readers_); + error = errno; + } + else + result = 0; + + ACE_OS::mutex_unlock (&rw->lock_); + errno = error; + return result; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_wrlock (ACE_rwlock_t *rw) +{ +// ACE_TRACE ("ACE_OS::rw_wrlock"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_wrlock (rw), _result), int, -1); +#else // NT, POSIX, and VxWorks don't support this natively. +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + pthread_cleanup_push (ACE_OS::mutex_lock_cleanup, (void *) &rw->lock_); +#endif + 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_DCETHREADS) || defined (ACE_HAS_PTHREADS) + pthread_cleanup_pop (0); +#endif + return 0; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rwlock_init (ACE_rwlock_t *rw, + int type, + LPCTSTR name, + void *arg) +{ +// ACE_TRACE ("ACE_OS::rwlock_init"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_init (rw, type, arg), _result), int, -1); +#else // NT, POSIX, and VxWorks don't support this natively. + int result = -1; + + if (ACE_OS::mutex_init (&rw->lock_, type, name, arg) == 0 + && ACE_OS::cond_init (&rw->waiting_readers_, type, name, arg) == 0 + && ACE_OS::cond_init (&rw->waiting_writers_, type, name, arg) == 0) + { + // Success! + rw->ref_count_ = 0; + rw->num_waiting_writers_ = 0; + rw->num_waiting_readers_ = 0; + + result = 0; + } + + if (result == -1) + { + int error = errno; + ACE_OS::mutex_destroy (&rw->lock_); + ACE_OS::cond_destroy (&rw->waiting_readers_); + ACE_OS::cond_destroy (&rw->waiting_writers_); + errno = error; + } + return result; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rwlock_destroy (ACE_rwlock_t *rw) +{ +// ACE_TRACE ("ACE_OS::rwlock_destroy"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_destroy (rw), _result), int, -1); +#else // NT, POSIX, and VxWorks don't support this natively. + ACE_OS::mutex_destroy (&rw->lock_); + ACE_OS::cond_destroy (&rw->waiting_readers_); + return ACE_OS::cond_destroy (&rw->waiting_writers_); +#endif /* ACE_HAS_STHREADS */ +#else + 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, + LPCTSTR name, + void *arg) +{ +#if defined (ACE_WIN32) + *event = ::CreateEvent (0, // no security attributes + manual_reset, + initial_state, + name); + if (*event == NULL) + ACE_FAIL_RETURN (-1); + else + return 0; +#elif defined (ACE_HAS_THREADS) + event->manual_reset_ = manual_reset; + event->is_signaled_ = initial_state; + event->waiting_threads_ = 0; + + int result = ACE_OS::cond_init (&event->condition_, + type, + name, + arg); + if (result == 0) + result = ACE_OS::mutex_init (&event->lock_, + type, + name, + arg); + return result; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_destroy (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), _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_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_wait (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + if (::WaitForSingleObject (*event, INFINITE) == WAIT_OBJECT_0) + return 0; + else + ACE_FAIL_RETURN (-1); +#elif defined (ACE_HAS_THREADS) + int wait_failed = 0; + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) != 0) + return -1; + + 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) + { + wait_failed = 1; + error = errno; + } + event->waiting_threads_--; + } + + // now we can let go of the lock + result = ACE_OS::mutex_unlock (&event->lock_); + + if (wait_failed) + { + // Reset errno in case mutex_unlock() also fails... + errno = error; + return -1; + } + else + return result; + +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ + +} + +ACE_INLINE int +ACE_OS::event_timedwait (ACE_event_t *event, + ACE_Time_Value *timeout) +{ +#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 <relative_time> 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). + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + result = ::WaitForSingleObject (*event, relative_time.msec ()); + } + if (result == WAIT_OBJECT_0) + return 0; + else + { + errno = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); + // This is a hack, we need to find an appropriate mapping... + return -1; + } +#elif defined (ACE_HAS_THREADS) + int wait_failed = 0; + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) != 0) + return -1; + + 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_timedwait (&event->condition_, + &event->lock_, + timeout) != 0) + { + wait_failed = 1; + error = errno; + } + event->waiting_threads_--; + } + + // now we can let go of the lock + result = ACE_OS::mutex_unlock (&event->lock_); + + if (wait_failed) + { + // Reset errno in case mutex_unlock() also fails... + errno = error; + return -1; + } + else + return result; + +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_signal (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), _result), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + int wakeup_failed = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) != 0) + return -1; + + // Manual-reset event. + if (event->manual_reset_ == 1) + { + // signal event + event->is_signaled_ = 1; + // wakeup all + if (ACE_OS::cond_broadcast (&event->condition_) != 0) + { + wakeup_failed = 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) + { + wakeup_failed = 1; + error = errno; + } + } + + // Now we can let go of the lock. + result = ACE_OS::mutex_unlock (&event->lock_); + + if (wakeup_failed) + { + // Reset errno in case mutex_unlock() also fails... + errno = error; + return -1; + } + else + return result; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_pulse (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), _result), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + int wakeup_failed = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) != 0) + return -1; + + // Manual-reset event. + if (event->manual_reset_ == 1) + { + // Wakeup all waiters. + if (ACE_OS::cond_broadcast (&event->condition_) != 0) + { + wakeup_failed = 1; + error = errno; + } + } + // Auto-reset event: wakeup one waiter. + else if (ACE_OS::cond_signal (&event->condition_) != 0) + { + wakeup_failed = 1; + error = errno; + } + + // Reset event. + event->is_signaled_ = 0; + + // Now we can let go of the lock. + result = ACE_OS::mutex_unlock (&event->lock_); + + if (wakeup_failed) + { + // Reset errno in case mutex_unlock() also fails... + errno = error; + return -1; + } + else + return result; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_reset (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), _result), int, -1); +#elif defined (ACE_HAS_THREADS) + // Grab the lock first. + if (ACE_OS::mutex_lock (&event->lock_) != 0) + return -1; + + // Reset event. + event->is_signaled_ = 0; + + // Now we can let go of the lock. + return ACE_OS::mutex_unlock (&event->lock_); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +#if defined (ACE_WIN32) +#define ACE_SOCKCALL_RETURN(OP,TYPE,FAILVALUE) \ + do { TYPE _result = (TYPE) OP; \ + if ((ACE_SOCKET) _result == SOCKET_ERROR) { errno = ::WSAGetLastError (); return (TYPE) FAILVALUE; } else return _result; \ + } while (0) +#else +#define ACE_SOCKCALL_RETURN(OP,TYPE,FAILVALUE) ACE_OSCALL_RETURN(OP,TYPE,FAILVALUE) +#endif /* ACE_WIN32 */ + +ACE_INLINE char * +ACE_OS::strcat (char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strcat"); + return ::strcat (s, t); +} + +ACE_INLINE char * +ACE_OS::strstr (const char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strstr"); + return ::strstr (s, t); +} + +ACE_INLINE size_t +ACE_OS::strspn (const char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strstr"); + return ::strspn (s, t); +} + +ACE_INLINE char * +ACE_OS::strchr (const char *s, int c) +{ +// ACE_TRACE ("ACE_OS::strchr"); + return ::strchr (s, c); +} + +ACE_INLINE char * +ACE_OS::strrchr (const char *s, int c) +{ +// ACE_TRACE ("ACE_OS::strrchr"); + return ::strrchr (s, c); +} + +ACE_INLINE int +ACE_OS::strcmp (const char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strcmp"); + return ::strcmp (s, t); +} + +ACE_INLINE char * +ACE_OS::strcpy (char *s, const char *t) +{ +// ACE_TRACE ("ACE_OS::strcpy"); + return ::strcpy (s, t); +} + +ACE_INLINE char * +ACE_OS::strdup (const char *s) +{ +// ACE_TRACE ("ACE_OS::strdup"); +#if defined (VXWORKS) + char *t = (char *) ::malloc (::strlen (s) + 1); + if (t == 0) + return 0; + else + return ACE_OS::strcpy (t, s); +#else + return ::strdup (s); +#endif /* VXWORKS */ +} + +ACE_INLINE size_t +ACE_OS::strlen (const char *s) +{ +// ACE_TRACE ("ACE_OS::strlen"); + return ::strlen (s); +} + +ACE_INLINE int +ACE_OS::strncmp (const char *s, const char *t, size_t len) +{ +// ACE_TRACE ("ACE_OS::strncmp"); + return ::strncmp (s, t, len); +} + +ACE_INLINE char * +ACE_OS::strncpy (char *s, const char *t, size_t len) +{ +// ACE_TRACE ("ACE_OS::strncpy"); + return ::strncpy (s, t, len); +} + +ACE_INLINE char * +ACE_OS::strtok (char *s, const char *tokens) +{ +// ACE_TRACE ("ACE_OS::strtok"); + return ::strtok (s, tokens); +} + +ACE_INLINE char * +ACE_OS::strtok_r (char *s, const char *tokens, char **lasts) +{ +// ACE_TRACE ("ACE_OS::strtok_r"); +#if defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) + return ::strtok_r (s, tokens, lasts); +#else + return ::strtok (s, tokens); +#endif /* (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) */ +} + +ACE_INLINE long +ACE_OS::strtol (const char *s, char **ptr, int base) +{ +// ACE_TRACE ("ACE_OS::strtol"); + return ::strtol (s, ptr, base); +} + +ACE_INLINE ACE_HANDLE +ACE_OS::accept (ACE_HANDLE handle, struct sockaddr *addr, + int *addrlen) +{ +// ACE_TRACE ("ACE_OS::accept"); + ACE_SOCKCALL_RETURN (::accept ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), + ACE_HANDLE, ACE_INVALID_HANDLE); +} + +ACE_INLINE int +ACE_OS::bind (ACE_HANDLE handle, struct sockaddr *addr, int addrlen) +{ +// ACE_TRACE ("ACE_OS::bind"); + ACE_SOCKCALL_RETURN (::bind ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN) addrlen), int, -1); +} + +ACE_INLINE int +ACE_OS::connect (ACE_HANDLE handle, struct sockaddr *addr, int addrlen) +{ +// ACE_TRACE ("ACE_OS::connect"); + ACE_SOCKCALL_RETURN (::connect ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN) addrlen), int, -1); +} + +ACE_INLINE struct hostent * +ACE_OS::gethostbyaddr (const char *addr, int length, int type) +{ +// ACE_TRACE ("ACE_OS::gethostbyaddr"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_NONCONST_GETBY) + char laddr[length]; + ACE_OS::memcpy(laddr, addr, (size_t)length); + ACE_SOCKCALL_RETURN (::gethostbyaddr (laddr, (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::gethostbyname (const char *name) +{ +// ACE_TRACE ("ACE_OS::gethostbyname"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_NONCONST_GETBY) + char lname[::strlen (name) + 1]; + ACE_OS::strcpy (lname, name); + ACE_SOCKCALL_RETURN (::gethostbyname (lname), struct hostent *, 0); +#else + ACE_SOCKCALL_RETURN (::gethostbyname (name), struct hostent *, 0); +#endif /* ACE_HAS_NONCONST_GETBY */ +} + +ACE_INLINE int +ACE_OS::select (int width, + fd_set *rfds, fd_set *wfds, fd_set *efds, + ACE_Time_Value *timeout) +{ +// ACE_TRACE ("ACE_OS::select"); + ACE_SOCKCALL_RETURN (::select (width, + (ACE_FD_SET_TYPE *) rfds, + (ACE_FD_SET_TYPE *) wfds, + (ACE_FD_SET_TYPE *) efds, + (timeval *) timeout) , 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_TRACE ("ACE_OS::select"); + ACE_SOCKCALL_RETURN (::select (width, + (ACE_FD_SET_TYPE *) rfds, + (ACE_FD_SET_TYPE *) wfds, + (ACE_FD_SET_TYPE *) efds, + (timeval *) &timeout) , int, -1); +} + +ACE_INLINE int +ACE_OS::recv (ACE_HANDLE handle, char *buf, int len, int flags) +{ +// ACE_TRACE ("ACE_OS::recv"); + ACE_SOCKCALL_RETURN (::recv ((ACE_SOCKET) handle, buf, len, flags), int, -1); +} + +ACE_INLINE int +ACE_OS::recvfrom (ACE_HANDLE handle, char *buf, int len, + int flags, struct sockaddr *addr, int *addrlen) +{ +// ACE_TRACE ("ACE_OS::recvfrom"); + ACE_SOCKCALL_RETURN (::recvfrom ((ACE_SOCKET) handle, buf, (ACE_SOCKET_LEN) len, flags, + addr, (ACE_SOCKET_LEN *) addrlen), + int, -1); +} + +ACE_INLINE int +ACE_OS::send (ACE_HANDLE handle, const char *buf, int len, int flags) +{ +// ACE_TRACE ("ACE_OS::send"); +#if defined (VXWORKS) || defined (HPUX) + ACE_SOCKCALL_RETURN (::send ((ACE_SOCKET) handle, (char *) buf, len, flags), int, ERROR); +#else + ACE_SOCKCALL_RETURN (::send ((ACE_SOCKET) handle, buf, len, flags), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::sendto (ACE_HANDLE handle, const char *buf, int len, + int flags, const struct sockaddr *addr, int addrlen) +{ +// ACE_TRACE ("ACE_OS::sendto"); +#if defined (VXWORKS) + ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, (char *) buf, len, flags, + (struct sockaddr *) addr, addrlen), int, ERROR); +#else + ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, buf, len, flags, + (struct sockaddr *) addr, addrlen), int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::getpeername (ACE_HANDLE handle, struct sockaddr *addr, + int *addrlen) +{ +// ACE_TRACE ("ACE_OS::getpeername"); + ACE_SOCKCALL_RETURN (::getpeername ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), + int, -1); +} + +ACE_INLINE struct protoent * +ACE_OS::getprotobyname (const char *name) +{ +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (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) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) +#if !defined (AIX) + ACE_SOCKCALL_RETURN (::getprotobyname_r (name, result, buffer, sizeof (ACE_PROTOENT_DATA)), + struct protoent *, 0); +#else + if (::getprotobyname_r (name, result, (struct protoent_data *) buffer) == 0) + return result; + else + return 0; +#endif /* !AIX */ +#else + ACE_SOCKCALL_RETURN (::getprotobyname (name), + struct protoent *, 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) */ +} + +ACE_INLINE struct protoent * +ACE_OS::getprotobynumber (int proto) +{ +#if defined (VXWORKS) + 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) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) +#if !defined (AIX) + ACE_SOCKCALL_RETURN (::getprotobynumber_r (proto, result, buffer, sizeof (ACE_PROTOENT_DATA)), + struct protoent *, 0); +#else + if (::getprotobynumber_r (proto, result, (struct protoent_data *) buffer) == 0) + return result; + else + return 0; +#endif /* !AIX */ +#else + ACE_SOCKCALL_RETURN (::getprotobynumber (proto), + struct protoent *, 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) */ +} + +ACE_INLINE struct servent * +ACE_OS::getservbyname (const char *svc, const char *proto) +{ +// ACE_TRACE ("ACE_OS::getservbyname"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_NONCONST_GETBY) + char lsvc[::strlen (svc) + 1]; + char lproto[::strlen (proto) + 1]; + ACE_OS::strcpy (lsvc, svc); + ACE_OS::strcpy (lproto, proto); + ACE_SOCKCALL_RETURN (::getservbyname (lsvc, lproto), + 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_TRACE ("ACE_OS::getsockname"); + + ACE_SOCKCALL_RETURN (::getsockname ((ACE_SOCKET) handle, addr, (ACE_SOCKET_LEN *) addrlen), + int, -1); +} + +ACE_INLINE int +ACE_OS::getsockopt (ACE_HANDLE handle, + int level, + int optname, + char *optval, + int *optlen) +{ +// ACE_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_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_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_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_TRACE ("ACE_OS::socket"); + ACE_SOCKCALL_RETURN (::socket (domain, type, proto), + ACE_HANDLE, ACE_INVALID_HANDLE); +} + +ACE_INLINE int +ACE_OS::atoi (const char *s) +{ +// ACE_TRACE ("ACE_OS::atoi"); + ACE_OSCALL_RETURN (::atoi (s), int, -1); +} + +ACE_INLINE int +ACE_OS::recvmsg (ACE_HANDLE handle, struct msghdr *msg, int flags) +{ +// ACE_TRACE ("ACE_OS::recvmsg"); +#if !defined (ACE_LACKS_RECVMSG) + ACE_OSCALL_RETURN (::recvmsg (handle, msg, flags), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_MSG */ +} + +ACE_INLINE int +ACE_OS::sendmsg (ACE_HANDLE handle, ACE_SENDMSG_TYPE *msg, int flags) +{ +// ACE_TRACE ("ACE_OS::sendmsg"); +#if !defined (ACE_LACKS_SENDMSG) +#if defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::sendmsg (handle, (struct msghdr *) msg, flags), int, -1); +#else + ACE_OSCALL_RETURN (::sendmsg (handle, msg, flags), int, -1); +#endif /* ACE_LACKS_POSIX_PROTO */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_MSG */ +} + +ACE_INLINE int +ACE_OS::fclose (FILE *fp) +{ +// ACE_TRACE ("ACE_OS::fclose"); + ACE_OSCALL_RETURN (::fclose (fp), int, -1); +} + +ACE_INLINE char * +ACE_OS::fgets (char *buf, int size, FILE *fp) +{ +// ACE_TRACE ("ACE_OS::fgets"); + ACE_OSCALL_RETURN (::fgets (buf, size, fp), char *, 0); +} + +ACE_INLINE int +ACE_OS::fflush (FILE *fp) +{ +// ACE_TRACE ("ACE_OS::fflush"); + ACE_OSCALL_RETURN (::fflush (fp), int, -1); +} + +ACE_INLINE FILE * +ACE_OS::fopen (const char *filename, const char *mode) +{ +// ACE_TRACE ("ACE_OS::fopen"); + ACE_OSCALL_RETURN (::fopen (filename, mode), FILE *, 0); +} + +ACE_INLINE int +ACE_OS::fprintf (FILE *fp, const char *format, ...) +{ +// ACE_TRACE ("ACE_OS::fprintf"); + int result = 0; + va_list ap; + va_start (ap, format); + ACE_OSCALL (::vfprintf (fp, format, ap), int, -1, result); + va_end (ap); + return result; +} + +ACE_INLINE size_t +ACE_OS::fread (void *ptr, size_t size, size_t nelems, FILE *fp) +{ +// ACE_TRACE ("ACE_OS::fread"); +#if defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::fread ((char *) ptr, size, nelems, fp), int, 0); +#else + ACE_OSCALL_RETURN (::fread (ptr, size, nelems, fp), int, 0); +#endif /* ACE_LACKS_POSIX_PROTO */ +} + +ACE_INLINE size_t +ACE_OS::fwrite (const void *ptr, size_t size, size_t nitems, FILE *fp) +{ +// ACE_TRACE ("ACE_OS::fwrite"); +#if defined (ACE_LACKS_POSIX_PROTO) + 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_LACKS_POSIX_PROTO */ +} + +ACE_INLINE void * +ACE_OS::malloc (size_t nbytes) +{ +// ACE_TRACE ("ACE_OS::malloc"); + return ::malloc (nbytes); +} + +ACE_INLINE void * +ACE_OS::realloc (void *ptr, size_t nbytes) +{ +// ACE_TRACE ("ACE_OS::realloc"); + return ::realloc (ACE_MALLOC_T (ptr), nbytes); +} + +ACE_INLINE void +ACE_OS::free (void *ptr) +{ +// ACE_TRACE ("ACE_OS::free"); + ::free (ACE_MALLOC_T (ptr)); +} + +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_TRACE ("ACE_OS::gethostbyaddr_r"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) +#if !defined (AIX) + ACE_SOCKCALL_RETURN (::gethostbyaddr_r (addr, length, type, result, + buffer, sizeof (ACE_HOSTENT_DATA), + h_errnop), + struct hostent *, 0); +#else + ::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; + } +#endif /* !defined (AIX) */ +#elif defined (ACE_HAS_NONCONST_GETBY) + char laddr[length]; + ACE_OS::memcpy (laddr, addr, (size_t) length); + ACE_SOCKCALL_RETURN (::gethostbyaddr (laddr, (ACE_SOCKET_LEN) length, type), + struct hostent *, 0); +#else + ACE_SOCKCALL_RETURN (::gethostbyaddr (addr, (ACE_SOCKET_LEN) length, type), + struct hostent *, 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) */ +} + +ACE_INLINE struct hostent * +ACE_OS::gethostbyname_r (const char *name, hostent *result, + ACE_HOSTENT_DATA buffer, + int *h_errnop) +{ +// ACE_TRACE ("ACE_OS::gethostbyname_r"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) +#if !defined (AIX) + ACE_SOCKCALL_RETURN (::gethostbyname_r (name, result, buffer, + sizeof (ACE_HOSTENT_DATA), h_errnop), + struct hostent *, 0); +#else + ::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; + } +#endif /* ! defined (AIX) */ +#elif defined (ACE_HAS_NONCONST_GETBY) + char lname[::strlen (name) + 1]; + ACE_OS::strcpy (lname, name); + ACE_SOCKCALL_RETURN (::gethostbyname (lname), struct hostent *, 0); +#else + ACE_SOCKCALL_RETURN (::gethostbyname (name), struct hostent *, 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) */ +} + +ACE_INLINE char * +ACE_OS::gets (char *str) +{ +// ACE_TRACE ("ACE_OS::gets"); + ACE_OSCALL_RETURN (::gets (str), char *, 0); +} + +ACE_INLINE struct servent * +ACE_OS::getservbyname_r (const char *svc, const char *proto, + struct servent *result, ACE_SERVENT_DATA buf) +{ +// ACE_TRACE ("ACE_OS::getservbyname_r"); +#if defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) +#if !defined (AIX) + ACE_SOCKCALL_RETURN (::getservbyname_r (svc, proto, result, buf, + sizeof (ACE_SERVENT_DATA)), + struct servent *, 0); +#else + ::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; +#endif /* !defined (AIX) */ +#elif defined (ACE_HAS_NONCONST_GETBY) + char lsvc[::strlen (svc) + 1]; + char lproto[::strlen (proto) + 1]; + ACE_OS::strcpy (lsvc, svc); + ACE_OS::strcpy (lproto, proto); + ACE_SOCKCALL_RETURN (::getservbyname (lsvc, lproto), + struct servent *, 0); +#else + ACE_SOCKCALL_RETURN (::getservbyname (svc, proto), + struct servent *, 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) && !defined (UNIXWARE) */ +} + +ACE_INLINE long +ACE_OS::inet_addr (const char *name) +{ +// ACE_TRACE ("ACE_OS::inet_addr"); +#if defined (VXWORKS) + + u_long retval = 0; + u_int segment; + + for (u_int i = 0; i < 4; ++i) + { + retval <<= 8; + if (*name != '\0') + { + segment = 0; + + while (*name >= '0' && *name <= '9') + { + segment *= 10; + segment += *name++ - '0'; + } + retval |= segment; + + if (*name == '.') + { + ++name; + } + } + } + return (long) htonl (retval); +#elif defined (ACE_HAS_NONCONST_GETBY) + char _name[::strlen (name) + 1]; + ACE_OS::strcpy (_name, name); + return ::inet_addr (_name); +#else + return ::inet_addr (name); +#endif /* ACE_HAS_NONCONST_GETBY */ +} + +ACE_INLINE char * +ACE_OS::inet_ntoa (const struct in_addr addr) +{ +// ACE_TRACE ("ACE_OS::inet_ntoa"); +#if defined (VXWORKS) + // the following storage is not thread-specific! + static char buf[32]; + // assumes that addr is already in network byte order + sprintf (buf, "%d.%d.%d.%d", addr.S_un.S_addr / (256*256*256) & 255, + addr.S_un.S_addr / (256*256) & 255, + addr.S_un.S_addr / 256 & 255, + addr.S_un.S_addr & 255); + return buf; +#else + ACE_OSCALL_RETURN (::inet_ntoa (addr), char *, 0); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::last_error (void) +{ +// ACE_TRACE ("ACE_OS::last_error"); +#if defined (ACE_WIN32) + return ::GetLastError (); +#else + return errno; +#endif /* ACE_HAS_WIN32 */ +} + +ACE_INLINE void +ACE_OS::last_error (int error) +{ +// ACE_TRACE ("ACE_OS::last_error"); +#if defined (ACE_WIN32) + ::SetLastError (error); +#else + errno = error; +#endif /* ACE_HAS_WIN32 */ +} + +ACE_INLINE void +ACE_OS::perror (const char *s) +{ +// ACE_TRACE ("ACE_OS::perror"); + ::perror (s); +} + +ACE_INLINE int +ACE_OS::printf (const char *format, ...) +{ +// ACE_TRACE ("ACE_OS::printf"); + int result; + va_list ap; + va_start (ap, format); + ACE_OSCALL (::vprintf (format, ap), int, -1, result); + va_end (ap); + return result; +} + +ACE_INLINE int +ACE_OS::puts (const char *s) +{ +// ACE_TRACE ("ACE_OS::puts"); + ACE_OSCALL_RETURN (::puts (s), int, -1); +} + +ACE_INLINE int +ACE_OS::sema_destroy (ACE_sema_t *s) +{ +// ACE_TRACE ("ACE_OS::sema_destroy"); +#if defined (ACE_HAS_POSIX_SEM) + if (s->name_) + { + ACE_OS::free ((void *) s->name_); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_unlink (s->name_), _result), int, -1); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_close (s->sema_), _result), int, -1); + } + else + { + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_destroy (s->sema_), _result), int, -1); + delete s->sema_; + s->sema_ = 0; + } +#elif defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_destroy (s), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || 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) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*s), _result), int, -1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POSIX_SEM */ +} + +ACE_INLINE int +ACE_OS::sema_init (ACE_sema_t *s, u_int count, int type, + LPCTSTR name, void *arg, int max) +{ +// ACE_TRACE ("ACE_OS::sema_init"); +#if defined (ACE_HAS_POSIX_SEM) + if (name) + { + s->name_ = ACE_OS::strdup (name); + s->sema_ = ::sem_open (s->name_, O_CREAT, ACE_DEFAULT_PERMS, count); + return (int) s->sema_ == -1 ? -1 : 0; + } + else + { + s->name_ = 0; + ACE_NEW_RETURN (s->sema_, sem_t, -1); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_init (s->sema_, type != USYNC_THREAD, count), _result), + int, -1); + } +#elif defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_init (s, count, type, arg), _result), + int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + int result = -1; + + if (ACE_OS::mutex_init (&s->lock_, type, name, arg) == 0 + && ACE_OS::cond_init (&s->count_nonzero_, type, name, arg) == 0 + && ACE_OS::mutex_lock (&s->lock_) == 0) + { + s->count_ = count; + 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) + // Create the semaphore with its value initialized to <count> and + // its maximum value initialized to <max>. + *s = ::CreateSemaphore (0, count, max, name); + + if (*s == 0) + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ + else + return 0; +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POSIX_SEM */ +} + +ACE_INLINE int +ACE_OS::sema_post (ACE_sema_t *s) +{ +// ACE_TRACE ("ACE_OS::sema_post"); +#if defined (ACE_HAS_POSIX_SEM) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_post (s->sema_), _result), int, -1); +#elif defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_post (s), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + + int result = -1; + int count_was_zero; + + if (ACE_OS::mutex_lock (&s->lock_) == 0) + { + count_was_zero = s->count_++ == 0; + if (ACE_OS::mutex_unlock (&s->lock_) == 0) + { + if (count_was_zero) + // Allows a waiter to continue. + result = ACE_OS::cond_signal (&s->count_nonzero_); + else + result = 0; + } + } + return result; +#elif defined (ACE_HAS_WTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, 1, 0), + _result), + int, -1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POSIX_SEM */ +} + +ACE_INLINE int +ACE_OS::sema_trywait (ACE_sema_t *s) +{ +// ACE_TRACE ("ACE_OS::sema_trywait"); +#if defined (ACE_HAS_POSIX_SEM) + // POSIX semaphores set errno to EAGAIN if trywait fails + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_trywait (s->sema_), _result), + 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), + _result), + int, -1); +#elif defined (ACE_HAS_DCETHREADS) || 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) + int result = ::WaitForSingleObject (*s, 0); + + if (result == WAIT_OBJECT_0) + return 0; + else + { + errno = result == WAIT_TIMEOUT ? EBUSY : ::GetLastError (); + // This is a hack, we need to find an appropriate mapping... + return -1; + } + +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POSIX_SEM */ +} + +ACE_INLINE int +ACE_OS::sema_wait (ACE_sema_t *s) +{ +// ACE_TRACE ("ACE_OS::sema_wait"); +#if defined (ACE_HAS_POSIX_SEM) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sem_wait (s->sema_), _result), int, -1); +#elif defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_wait (s), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + int result = 0; + + pthread_cleanup_push (ACE_OS::mutex_lock_cleanup, (void *) &s->lock_); + + if (ACE_OS::mutex_lock (&s->lock_) != 0) + result = -1; + else + { + while (s->count_ == 0) + if (ACE_OS::cond_wait (&s->count_nonzero_, &s->lock_) == -1) + { + result = -2; + break; + } + } + + if (result == 0) + --s->count_; + if (result != -1) + ACE_OS::mutex_unlock (&s->lock_); + pthread_cleanup_pop (1); + return result; + +#elif defined (ACE_HAS_WTHREADS) + if (::WaitForSingleObject (*s, INFINITE) == WAIT_OBJECT_0) + return 0; + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POSIX_SEM */ +} + +ACE_INLINE ACE_SignalHandler +ACE_OS::signal (int signum, ACE_SignalHandler func) +{ + return ::signal (signum, func); +} + +ACE_INLINE int +ACE_OS::sprintf (char *buf, const char *format, ...) +{ +// ACE_TRACE ("ACE_OS::sprintf"); + int result; + va_list ap; + va_start (ap, format); + ACE_OSCALL (::vsprintf (buf, format, ap), int, -1, result); + va_end (ap); + return result; +} + +ACE_INLINE int +ACE_OS::system (const char *s) +{ +// ACE_TRACE ("ACE_OS::system"); + ACE_OSCALL_RETURN (::system (s), int, -1); +} + +ACE_INLINE int +ACE_OS::thr_continue (ACE_hthread_t target_thread) +{ +// ACE_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), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + return ::ResumeThread (target_thread) != ACE_SYSCALL_FAILED ? 0 : -1; +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::taskResume (target_thread), _result), int, ERROR); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_equal (ACE_thread_t t1, ACE_thread_t t2) +{ +#if defined (ACE_HAS_DCETHREADS) || 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? + return t1 == t2; +#endif /* ACE_HAS_DCETHREADS */ +} + +ACE_INLINE int +ACE_OS::thr_cmp (ACE_hthread_t t1, ACE_hthread_t t2) +{ +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) +#if defined (ACE_HAS_TID_T) && !defined (ACE_HAS_SETKIND_NP) + return t1 == t2; // I hope these aren't structs! +#elif 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? + return t1 == t2; +#endif /* ACE_HAS_DCETHREADS */ +} + +ACE_INLINE int +ACE_OS::thr_getconcurrency (void) +{ +// ACE_TRACE ("ACE_OS::thr_getconcurrency"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + return ::thr_getconcurrency (); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) || defined (VXWORKS) + 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_TRACE ("ACE_OS::thr_getprio"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getprio (thr_id, prio), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + + int result = ::GetThreadPriority (thr_id); + return result == THREAD_PRIORITY_ERROR_RETURN ? -1 : result; +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::taskPriorityGet (thr_id, prio), _result), int, ERROR); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data) +{ +// ACE_TRACE ("ACE_OS::thr_getspecific"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getspecific (key, data), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) +#if !defined (ACE_HAS_FSU_PTHREADS) && !defined (ACE_HAS_SETKIND_NP) + *data = ::pthread_getspecific (key); +#elif !defined (ACE_HAS_FSU_PTHREADS) && defined (ACE_HAS_SETKIND_NP) + ::pthread_getspecific (key, data); +#else /* ACE_HAS_FSU_PTHREADS */ + // Is this really used anywhere? + *data = ::pthread_getspecific (key, data); +#endif /* ACE_HAS_FSU_PTHREADS */ + return 0; +#elif defined (ACE_HAS_WTHREADS) + *data = ::TlsGetValue (key); + return 0; +#elif defined (VXWORKS) + // VxWorks doesn't support thread specific storage, though it's probably + // doable without too much trouble . . . + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +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) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (waiter_id, thr_id, status), _result), + int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_join (waiter_id, status), _result), + int, -1); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_join (ACE_hthread_t thr_handle, void **status) +{ +// ACE_TRACE ("ACE_OS::thr_join"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + 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) + // VxWorks could possibly support thread join with + // ::taskSafe()/::taskUnsafe(). But, a task can only calls those + // functions on itself. Until there's really a need . . . + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_setcancelstate (int new_state, int *old_state) +{ +// ACE_TRACE ("ACE_OS::thr_setcancelstate"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || (defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_STHREADS)) +#if defined (ACE_HAS_SETKIND_NP) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setcancel (new_state), + _result), + int, -1); +#else /* ACE_HAS_SETKIND_NP */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setcancelstate (new_state, old_state), + _result), + int, -1); +#endif /* ACE_HAS_SETKIND_NP */ +#elif defined (ACE_HAS_PTHREADS) +// I didn't manage to find pthread_cancel anywhere in the MIT pthread +// implementation. So I'll just leave this instead, and see what +// breaks. -- jwr + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_STHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_setcanceltype (int new_type, int *old_type) +{ +// ACE_TRACE ("ACE_OS::thr_setcanceltype"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || (defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_STHREADS)) +#if defined (ACE_HAS_SETKIND_NP) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setcancel (new_type), + _result), + int, -1); +#else /* ACE_HAS_SETKIND_NP */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setcanceltype (new_type, old_type), + _result), + int, -1); +#endif /* ACE_HAS_SETKIND_NP */ +#elif defined (ACE_HAS_PTHREADS) +// I didn't manage to find pthread_cancel anywhere int the MIT pthread +// implementation. So I'll just leave this instead, and see what +// breaks. -- jwr + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_STHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_cancel (ACE_thread_t t_id) +{ +// ACE_TRACE ("ACE_OS::thr_cancel"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || (defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_STHREADS)) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cancel(t_id), + _result), + int, -1); +#elif defined (ACE_HAS_PTHREADS) +// I didn't manage to find pthread_cancel anywhere int the MIT +// pthread implementation. So I'll just leave this instead, and +// see what breaks. -- jwr + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_STHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::sigwait (sigset_t *set, int *sig) +{ +// ACE_TRACE ("ACE_OS::sigwait"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_FSU_PTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigwait (set), + _result), + int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) +#if defined (ACE_HAS_SETKIND_NP) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigwait (set), + _result), + int, -1); +#else /* ACE_HAS_SETKIND_NP */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigwait (set, sig), + _result), + int, -1); +#endif /* ACE_HAS_SETKIND_NP */ +#elif defined (ACE_HAS_WTHREADS) + 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: NULL means forever + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigtimedwait (set, NULL, NULL), + _result), + int, -1); // yes, the doc says -1, not ERROR +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE void +ACE_OS::thr_testcancel (void) +{ +// ACE_TRACE ("ACE_OS::thr_testcancel"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || (defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_STHREADS)) + ::pthread_testcancel (); +#elif defined (ACE_HAS_PTHREADS) +// I didn't manage to find pthread_cancel anywhere int the MIT +// pthread implementation. So I'll just leave this instead, and +// see what breaks. -- jwr +#elif defined (ACE_HAS_STHREADS) +#elif defined (ACE_HAS_WTHREADS) +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_sigsetmask (int how, + const sigset_t *nsm, + sigset_t *osm) +{ +// ACE_TRACE ("ACE_OS::thr_sigsetmask"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_sigsetmask (how, nsm, osm), + _result), + int, -1); +#elif defined (ACE_HAS_SETKIND_NP) + // ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigaction (how, nsm, osm), + // _result), + // int, -1); + // commented this out since nothing appropriate + // found in the man pages... + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_DCETHREADS) +#if defined (ACE_HAS_PTHREADS_1003_DOT_1C) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigaction (how, nsm, osm), + _result), int, -1); +#else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigthreadmask (how, nsm, osm), + _result), int, -1); +#endif /* ACE_HAS_PTHREADS_1003_DOT_1C */ + +#elif defined (ACE_HAS_PTHREADS) && !defined (ACE_HAS_FSU_PTHREADS) +#if defined (ACE_HAS_IRIX62_THREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm), + _result),int, -1); +#else +// as far as I can tell, this is now pthread_sigaction() -- jwr + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigaction (how, nsm, osm), + _result), int, -1); +#endif /* ACE_HAS_IRIX62_THREADS */ +#elif defined (ACE_HAS_WTHREADS) + 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 an int, + // so abitwise operations can be done simply . . . + ::sigsetmask (how == SIG_BLOCK ? (*osm |= *nsm) : (*osm &= ~*nsm)); + break; + } + case SIG_SETMASK: + *osm = ::sigsetmask (nsm); + break; + default: + return -1; + } + + return 0; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigprocmask (how, nsm, osm), + _result), + int, -1); +#else // Should not happen. + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE size_t +ACE_OS::thr_min_stack (void) +{ +// ACE_TRACE ("ACE_OS::thr_min_stack"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_min_stack (), + _result), + int, -1); +#elif (defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)) && !defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_IRIX62_THREADS) + return (size_t) ACE_OS::sysconf (_SC_THREAD_STACK_MIN); +#else + return PTHREAD_STACK_MIN; +#endif /* ACE_HAS_IRIX62_THREADS */ +#elif (defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)) && !defined (ACE_HAS_SETKIND_NP) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (0); +#elif defined (VXWORKS) + TASK_DESC taskDesc; + STATUS status; + ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (ACE_OS::thr_self (), &taskDesc), + _result), + int, ERROR, status); + return status == 0 ? 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_kill (ACE_thread_t thr_id, int signum) +{ +// ACE_TRACE ("ACE_OS::thr_kill"); +#if defined (ACE_HAS_THREADS) +#if (defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)) && !defined (ACE_HAS_SETKIND_NP) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_kill (thr_id, signum), + _result), + int, -1); +#elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_kill (thr_id, signum), + _result), + int, -1); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + ACE_htread_t tid; + ACE_OSCALL (ACE_ADAPT_RETVAL (::taskNameToId (thr_id), _result), + int, ERROR, tid); + + if ( tid == ERROR ) + return -1; + else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::kill (tid, signum), _result), + int, ERROR); + +#else // This should not happen! + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE void +ACE_OS::thr_self (ACE_hthread_t &self) +{ +// ACE_TRACE ("ACE_OS::thr_self"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_SETKIND_NP) || defined (ACE_HAS_IRIX62_THREADS) + self = ::pthread_self (); +#elif defined (ACE_HAS_DCETHREADS) + self = ::thread_self (); +#elif defined (ACE_HAS_STHREADS) + self = ::thr_self (); +#elif defined (ACE_HAS_WTHREADS) + self = ::GetCurrentThread (); +#elif defined (VXWORKS) + self = ::taskIdSelf (); +#endif /* ACE_HAS_STHREADS */ +#else + self = 1; // Might as well make it the first thread ;-) +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE ACE_thread_t +ACE_OS::thr_self (void) +{ +// ACE_TRACE ("ACE_OS::thr_self"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + 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 (VXWORKS) + return ::taskIdSelf (); +#endif /* ACE_HAS_STHREADS */ +#else + return 1; // Might as well make it the first thread ;-) +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_setconcurrency (int hint) +{ +// ACE_TRACE ("ACE_OS::thr_setconcurrency"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setconcurrency (hint), + _result), + int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_setprio (ACE_hthread_t thr_id, int prio) +{ +// ACE_TRACE ("ACE_OS::thr_setprio"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setprio (thr_id, prio), + _result), + int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SetThreadPriority (thr_id, prio), + _result), + int, -1); +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::taskPrioritySet (thr_id, prio), _result), int, ERROR); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_suspend (ACE_hthread_t target_thread) +{ +// ACE_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), _result), int, -1); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WTHREADS) + + if (::SuspendThread (target_thread) != ACE_SYSCALL_FAILED) + return 0; + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::taskSuspend (target_thread), _result), int, ERROR); +#endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE void +ACE_OS::thr_yield (void) +{ +// ACE_TRACE ("ACE_OS::thr_yield"); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_STHREADS) + ::thr_yield (); +#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) +#if defined (ACE_HAS_IRIX62_THREADS) || defined (ACE_HAS_PTHREADS_1003_DOT_1C) + ::sched_yield (); +#elif defined (ACE_HAS_FSU_PTHREADS) || defined (ACE_HAS_YIELD_VOID_PTR) + ::pthread_yield (NULL); +#else + ::pthread_yield (); +#endif // ACE_HAS_IRIX62_THREADS */ +#elif defined (ACE_HAS_WTHREADS) + ::Sleep (0); +#elif defined (VXWORKS) + ::taskDelay (0); +#endif /* ACE_HAS_STHREADS */ +#else + ; +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE void +ACE_OS::rewind (FILE *fp) +{ +// ACE_TRACE ("ACE_OS::rewind"); + ::rewind (fp); +} + +// This function returns the number of bytes in the file referenced by +// FD. + +ACE_INLINE long +ACE_OS::filesize (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE::filesize"); +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (::GetFileSize (handle, NULL), int, ACE_SYSCALL_FAILED); +#else /* !ACE_WIN32 */ + struct stat sb; + + return ACE_OS::fstat (handle, &sb) == -1 ? (long) -1 : sb.st_size; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::writev (ACE_HANDLE handle, + ACE_WRITEV_TYPE *iov, + int iovcnt) +{ +// ACE_TRACE ("ACE_OS::writev"); + ACE_OSCALL_RETURN (::writev (handle, iov, iovcnt), int, -1); +} + +ACE_INLINE ssize_t +ACE_OS::readv (ACE_HANDLE handle, + struct iovec *iov, + int iovlen) +{ +// ACE_TRACE ("ACE_OS::readv"); + ACE_OSCALL_RETURN (::readv (handle, iov, iovlen), ssize_t, -1); +} + +ACE_INLINE ACE_Time_Value +ACE_OS::gettimeofday (void) +{ +// ACE_TRACE ("ACE_OS::gettimeofday"); + timeval tv; +#if defined (ACE_WIN32) + // From Todd Montgomery... + struct _timeb tb; + ::_ftime (&tb); + tv.tv_sec = tb.time; + tv.tv_usec = 1000 * tb.millitm; +#if 0 + // This version of the code has bugs -- don't use until it's been fixed... + // Alternative form. + SYSTEMTIME system_time; + FILETIME file_time; + + ::GetSystemTime (&system_time); + ::SystemTimeToFileTime (&system_time, &file_time); + ACE_QWORD _100ns = ACE_MAKE_QWORD (file_time.dwLowDateTime, + file_time.dwHighDateTime); + // Convert 100ns units to seconds; + tv.tv_sec = long (_100ns / (10000 * 1000)); + // Convert remainder to microseconds; + tv.tv_usec = long ((_100ns - (tv.tv_sec * (10000 * 1000))) * 10); +#endif +#else + int result; +#if defined (ACE_HAS_TIMEZONE_GETTIMEOFDAY) || (defined (ACE_HAS_SVR4_GETTIMEOFDAY) && !defined (m88k)) + ACE_OSCALL (::gettimeofday (&tv, 0), int, -1, result); +#elif defined (VXWORKS) + // assumes that struct timespec is same size as struct timeval, + // which assumes that time_t is a long: it currently (v 5.2) is + ACE_OSCALL (ACE_ADAPT_RETVAL (::clock_gettime (CLOCK_REALTIME, (struct timespec *) &tv), _result), + int, ERROR, result); +#else + ACE_OSCALL (::gettimeofday (&tv), int, -1, result); +#endif /* ACE_HAS_SVR4_GETTIMEOFDAY */ +#endif /* ACE_WIN32 */ + return ACE_Time_Value (tv); +} + +ACE_INLINE int +ACE_OS::poll (struct pollfd *pollfds, u_long len, ACE_Time_Value *timeout) +{ +// ACE_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_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_TRACE ("ACE_OS::poll"); +#if defined (ACE_HAS_POLL) + ACE_OSCALL_RETURN (::poll (pollfds, len, int (timeout.msec ())), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POLL */ +} + +ACE_INLINE int +ACE_OS::t_accept (ACE_HANDLE handle, int reshandle, + struct t_call *call) +{ +// ACE_TRACE ("ACE_OS::t_accept"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_accept (handle, reshandle, call), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE char * +ACE_OS::t_alloc (ACE_HANDLE handle, int struct_type, + int fields) +{ +// ACE_TRACE ("ACE_OS::t_alloc"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_alloc (handle, struct_type, fields), + char *, 0); +#else + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_bind (ACE_HANDLE handle, struct t_bind *req, + struct t_bind *ret) +{ +// ACE_TRACE ("ACE_OS::t_bind"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_bind (handle, req, ret), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_close (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_close"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_close (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_connect(int fildes, + struct t_call *sndcall, + struct t_call *rcvcall) +{ +// ACE_TRACE ("ACE_OS::t_connect"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_connect (fildes, sndcall, rcvcall), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE void +ACE_OS::t_error (char *errmsg) +{ +// ACE_TRACE ("ACE_OS::t_error"); +#if defined (ACE_HAS_TLI) + ::t_error (errmsg); +#else +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_free (char *ptr, int struct_type) +{ +// ACE_TRACE ("ACE_OS::t_free"); +#if defined (ACE_HAS_TLI) + if (ptr != 0) + return 0; + ACE_OSCALL_RETURN (::t_free (ptr, struct_type), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_getinfo (ACE_HANDLE handle, struct t_info *info) +{ +// ACE_TRACE ("ACE_OS::t_getinfo"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_getinfo (handle, info), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_getname (ACE_HANDLE handle, + struct netbuf *namep, + int type) +{ +// ACE_TRACE ("ACE_OS::t_getname"); +#if defined (ACE_HAS_SVR4_TLI) + ACE_OSCALL_RETURN (::t_getname (handle, namep, type), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::t_getstate (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_getstate"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_getstate (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_listen (ACE_HANDLE handle, struct t_call *call) +{ +// ACE_TRACE ("ACE_OS::t_listen"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_listen (handle, call), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_look (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_look"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_look (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_open (char *path, int oflag, struct t_info *info) +{ +// ACE_TRACE ("ACE_OS::t_open"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_open (path, oflag, info), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_optmgmt (ACE_HANDLE handle, + struct t_optmgmt *req, + struct t_optmgmt *ret) +{ +// ACE_TRACE ("ACE_OS::t_optmgmt"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_optmgmt (handle, req, ret), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_rcv (ACE_HANDLE handle, + char *buf, + unsigned nbytes, + int *flags) +{ +// ACE_TRACE ("ACE_OS::t_rcv"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcv (handle, buf, nbytes, flags), + int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_rcvdis (ACE_HANDLE handle, struct t_discon *discon) +{ +// ACE_TRACE ("ACE_OS::t_rcvdis"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvdis (handle, discon), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_rcvrel (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_rcvrel"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvrel (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_rcvudata (ACE_HANDLE handle, + struct t_unitdata *unitdata, + int *flags) +{ +// ACE_TRACE ("ACE_OS::t_rcvudata"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvudata (handle, unitdata, flags), + int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_rcvuderr (ACE_HANDLE handle, struct t_uderr *uderr) +{ +// ACE_TRACE ("ACE_OS::t_rcvuderr"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvuderr (handle, uderr), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_snd (ACE_HANDLE handle, char *buf, unsigned nbytes, int flags) +{ +// ACE_TRACE ("ACE_OS::t_snd"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_snd (handle, buf, nbytes, flags), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_snddis (ACE_HANDLE handle, struct t_call *call) +{ +// ACE_TRACE ("ACE_OS::t_snddis"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_snddis (handle, call), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_sndrel (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_sndrel"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_sndrel (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_sync (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_sync"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_sync (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS::t_unbind (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::t_unbind"); +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_unbind (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE char * +ACE_OS::compile (const char *instring, char *expbuf, char *endbuf) +{ +// ACE_TRACE ("ACE_OS::compile"); +#if defined (ACE_HAS_REGEX) + ACE_OSCALL_RETURN (::compile (instring, expbuf, endbuf), char *, 0); +#else + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_REGEX */ +} + +ACE_INLINE int +ACE_OS::close (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::close"); +#if defined (ACE_WIN32) + return ::CloseHandle (handle) ? 0 : -1; +#else + ACE_OSCALL_RETURN (::close (handle), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::closesocket (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::close"); +#if defined (ACE_WIN32) + return ::closesocket ((u_int) handle) == 0 ? 0 : -1; +#else + ACE_OSCALL_RETURN (::close (handle), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::access (const char *path, int amode) +{ +// ACE_TRACE ("ACE_OS::access"); +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (::_access (path, amode), int, -1); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::access (path, amode), int, -1); +#endif /* ACE_WIN32 && VXWORKS */ +} + + +ACE_INLINE ACE_HANDLE +ACE_OS::creat (LPCTSTR filename, mode_t mode) +{ +// ACE_TRACE ("ACE_OS::creat"); +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_OS::open (filename, mode), + ACE_HANDLE, ACE_INVALID_HANDLE); +#else + ACE_OSCALL_RETURN (::creat (filename, mode), + ACE_HANDLE, ACE_INVALID_HANDLE); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::uname (struct utsname *name) +{ +// ACE_TRACE ("ACE_OS::uname"); +#if defined (ACE_WIN32) + size_t maxnamelen = sizeof name->nodename; + ::strcpy (name->sysname, "Win32"); + // Any ideas what these should be? + ::strcpy (name->release, "???"); + ::strcpy (name->version, "???"); + ::strcpy (name->machine, "???"); + + return ACE_OS::hostname (name->nodename, maxnamelen); +#elif defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::uname (name), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::hostname (char name[], size_t maxnamelen) +{ +// ACE_TRACE ("ACE_OS::uname"); +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::GetComputerName (name, LPDWORD (&maxnamelen)), + _result), int, -1); +#else /* !ACE_WIN32 */ + struct utsname host_info; + + if (ACE_OS::uname (&host_info) == -1) + return -1; + else + { + ACE_OS::strncpy (name, host_info.nodename, maxnamelen); + return 0; + } +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::msgctl (int msqid, int cmd, msqid_ds *val) +{ +// ACE_TRACE ("ACE_OS::msgctl"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::msgctl (msqid, cmd, val), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::msgget (key_t key, int msgflg) +{ +// ACE_TRACE ("ACE_OS::msgget"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::msgget (key, msgflg), int, -1); +#else + 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_TRACE ("ACE_OS::msgrcv"); +#if defined (ACE_HAS_SYSV_IPC) +#if defined (ACE_LACKS_POSIX_PROTO) + 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_PROTO */ +#else + 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_TRACE ("ACE_OS::msgsnd"); +#if defined (ACE_HAS_SYSV_IPC) +#if defined (ACE_LACKS_POSIX_PROTO) + 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_PROTO */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE u_int +ACE_OS::alarm (u_int delay) +{ +// ACE_TRACE ("ACE_OS::alarm"); + +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#else + return ::alarm (delay); +#endif /* ACE_WIN32 || VXWORKS */ +} + +ACE_INLINE int +ACE_OS::dlclose (void *handle) +{ +// ACE_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, "_fini"), void *, 0, ptr); + + if (ptr != 0) + (*((int (*)(void)) ptr)) (); // Call _fini hook explicitly. +#endif /* ACE_HAS_AUTOMATIC_INIT_FINI */ + ACE_OSCALL_RETURN (::dlclose (handle), int, -1); +#elif defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::FreeLibrary (handle), _result), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE char * +ACE_OS::dlerror (void) +{ +// ACE_TRACE ("ACE_OS::dlerror"); +#if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + ACE_OSCALL_RETURN (::dlerror (), char *, 0); +#else + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE void * +ACE_OS::dlopen (ACE_DL_TYPE filename, int mode) +{ +// ACE_TRACE ("ACE_OS::dlopen"); +#if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + void *handle; + ACE_OSCALL (::dlopen (filename, mode), void *, 0, handle); +#if !defined (ACE_HAS_AUTOMATIC_INIT_FINI) + // Some systems (e.g., SunOS4) do not automatically call _init(), so + // we'll have to call it manually. + + void *ptr; + + ACE_OSCALL (::dlsym (handle, "_init"), void *, 0, ptr); + + if (ptr != 0 && (*((int (*)(void)) ptr)) () == -1) // Call _init hook explicitly. + return 0; +#endif /* ACE_HAS_AUTOMATIC_INIT_FINI */ + return handle; +#elif defined (ACE_WIN32) + ACE_OSCALL_RETURN (::LoadLibrary (filename), void *, 0); +#else + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE void * +ACE_OS::dlsym (void *handle, ACE_DL_TYPE symbolname) +{ +// ACE_TRACE ("ACE_OS::dlsym"); +#if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) +#if defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::dlsym (handle, (char*) symbolname), void *, 0); +#else + ACE_OSCALL_RETURN (::dlsym (handle, symbolname), void *, 0); +#endif /* ACE_LACKS_POSIX_PROTO */ +#elif defined (ACE_WIN32) + ACE_OSCALL_RETURN (::GetProcAddress (handle, symbolname), void *, 0); +#else + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE void +ACE_OS::exit (int status) +{ +// ACE_TRACE ("ACE_OS::exit"); +#if defined (ACE_WIN32) + ::ExitProcess ((UINT) status); +#else + ::exit (status); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::step (const char *str, char *expbuf) +{ +// ACE_TRACE ("ACE_OS::step"); +#if defined (ACE_HAS_REGEX) + ACE_OSCALL_RETURN (::step (str, expbuf), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_REGEX */ +} + +ACE_INLINE long +ACE_OS::sysinfo (int cmd, char *buf, long count) +{ +// ACE_TRACE ("ACE_OS::sysinfo"); +#if defined (ACE_HAS_SYSINFO) + ACE_OSCALL_RETURN (::sysinfo (cmd, buf, count), long, -1); +#else + 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_TRACE ("ACE_OS::write"); +#if 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 + return -1; +#else +#if defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::write (handle, (const char *) 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_PROTO */ +#endif /* ACE_WIN32 */ +} + +ACE_INLINE ssize_t +ACE_OS::write (ACE_HANDLE handle, const void *buf, size_t nbyte, + ACE_OVERLAPPED *overlapped) +{ +// ACE_TRACE ("ACE_OS::write"); +#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_TRACE ("ACE_OS::read"); +#if defined (ACE_WIN32) + DWORD ok_len; + return ::ReadFile (handle, buf, len, &ok_len, 0) ? (ssize_t) ok_len : -1; +#else +#if defined (ACE_LACKS_POSIX_PROTO) || defined (ACE_HAS_CHARPTR_SOCKOPT) + ACE_OSCALL_RETURN (::read (handle, (char *) buf, len), ssize_t, -1); +#else + ACE_OSCALL_RETURN (::read (handle, buf, len), ssize_t, -1); +#endif /* ACE_LACKS_POSIX_PROTO */ +#endif /* ACE_WIN32 */ +} + +ACE_INLINE ssize_t +ACE_OS::read (ACE_HANDLE handle, void *buf, size_t len, + ACE_OVERLAPPED *overlapped) +{ +// ACE_TRACE ("ACE_OS::read"); +#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::getmsg (ACE_HANDLE handle, + struct strbuf *ctl, + struct strbuf *data, + int *flags) +{ +// ACE_TRACE ("ACE_OS::getmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::getmsg (handle, ctl, data, flags), int, -1); +#else + // 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_TRACE ("ACE_OS::getpmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::getpmsg (handle, ctl, data, band, flags), int, -1); +#else + // 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_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) + FILETIME dummy_1, dummy_2; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::GetProcessTimes (::GetCurrentProcess(), + &dummy_1, // start + &dummy_2, // exited + &ru->ru_stime, + &ru->ru_utime), + _result), + int, -1); +#else + ACE_OSCALL_RETURN (::getrusage (who, ru), int, -1); +#endif /* ACE_WIN32 */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSCALL_GETRUSAGE */ +} + +ACE_INLINE int +ACE_OS::isastream (ACE_HANDLE handle) +{ +// ACE_TRACE ("ACE_OS::isastream"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::isastream (handle), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +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) +{ +// ACE_TRACE ("ACE_OS::mmap"); +#if defined (ACE_WIN32) + int nt_flags; + 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) + *file_mapping = ::CreateFileMapping (file_handle, 0, + prot, 0, len, 0); + if (*file_mapping == 0) + ACE_FAIL_RETURN (MAP_FAILED); + /* NOTREACHED */ + + void *addr_mapping = ::MapViewOfFileEx (*file_mapping, nt_flags, 0, + off, len, addr); + + // 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); + /* NOTREACHED */ + else if (ACE_BIT_ENABLED (flags, MAP_FIXED) + && addr_mapping != addr) + { + errno = EINVAL; + return MAP_FAILED; + } + else + return addr_mapping; +#elif !defined (ACE_LACKS_MMAP) + ACE_OSCALL_RETURN ((void *) ::mmap ((ACE_MMAP_TYPE) addr, len, + prot, flags, file_handle, off), + void *, MAP_FAILED); +#else + ACE_NOTSUP_RETURN (MAP_FAILED); +#endif /*ACE_WIN32 */ +} + +// 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_TRACE ("ACE_OS::mprotect"); +#if defined (ACE_WIN32) + DWORD dummy; // Sigh! + return ::VirtualProtect(addr, len, prot, &dummy) ? 0 : -1; +#elif !defined (ACE_LACKS_MMAP) + ACE_OSCALL_RETURN (::mprotect ((ACE_MMAP_TYPE) addr, len, prot), int, -1); +#else + ACE_NOTSUP_RETURN ((int) MAP_FAILED); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::msync (void *addr, size_t len, int sync) +{ +// ACE_TRACE ("ACE_OS::msync"); +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::FlushViewOfFile (addr, len), _result), int, -1); +#elif !defined (ACE_LACKS_MSYNC) + ACE_OSCALL_RETURN (::msync ((ACE_MMAP_TYPE) addr, len, sync), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::munmap (void *addr, size_t len) +{ +// ACE_TRACE ("ACE_OS::munmap"); +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::UnmapViewOfFile (addr), _result), int, -1); +#elif !defined (ACE_LACKS_MMAP) + ACE_OSCALL_RETURN (::munmap ((ACE_MMAP_TYPE) addr, len), int, -1); +#else + ACE_NOTSUP_RETURN ((int) MAP_FAILED); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::madvise (caddr_t addr, size_t len, int advice) +{ +// ACE_TRACE ("ACE_OS::madvise"); +#if defined (ACE_WIN32) + ACE_NOTSUP_RETURN (-1); +#elif !defined (ACE_LACKS_MADVISE) + ACE_OSCALL_RETURN (::madvise (addr, len, advice), int, -1); +#else + 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_TRACE ("ACE_OS::putmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::putmsg (handle, ctl, data, flags), int, -1); +#else + 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_TRACE ("ACE_OS::putpmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::putpmsg (handle, ctl, data, band, flags), int, -1); +#else + 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_TRACE ("ACE_OS::semctl"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::semctl (int_id, semnum, cmd, value), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::semget (key_t key, int nsems, int flags) +{ +// ACE_TRACE ("ACE_OS::semget"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::semget (key, nsems, flags), int, -1); +#else + 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_TRACE ("ACE_OS::semop"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::semop (int_id, sops, nsops), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE void * +ACE_OS::shmat (int int_id, void *shmaddr, int shmflg) +{ +// ACE_TRACE ("ACE_OS::shmat"); +#if defined (ACE_HAS_SYSV_IPC) +#if defined (ACE_LACKS_POSIX_PROTO) + 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_PROTO */ +#else + 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_TRACE ("ACE_OS::shmctl"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::shmctl (int_id, cmd, buf), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::shmdt (void *shmaddr) +{ +// ACE_TRACE ("ACE_OS::shmdt"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::shmdt ((char *) shmaddr), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::shmget (key_t key, int size, int flags) +{ +// ACE_TRACE ("ACE_OS::shmget"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::shmget (key, size, flags), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE ACE_HANDLE +ACE_OS::open (LPCTSTR filename, + int mode, + int perms) +{ +// ACE_TRACE ("ACE_OS::open"); +#if defined (ACE_WIN32) + // Warning: This function ignores _O_APPEND + + 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 (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, FILE_FLAG_OVERLAPPED)) + flags = FILE_FLAG_OVERLAPPED; + if (ACE_BIT_ENABLED (mode, _O_TEMPORARY)) + flags |= FILE_FLAG_DELETE_ON_CLOSE; + + ACE_HANDLE h = ::CreateFile (filename, access, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, creation, + flags, + 0); + + if (h == ACE_INVALID_HANDLE) + { + switch ((errno = ::GetLastError ())) + { + case ERROR_FILE_EXISTS: + errno = EEXIST; + } + } + return h; +#else + ACE_OSCALL_RETURN (::open (filename, mode, perms), ACE_HANDLE, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE char * +ACE_OS::ctime (const time_t *t) +{ +// ACE_TRACE ("ACE_OS::ctime"); +#if defined (ACE_HAS_BROKEN_CTIME) + ACE_OSCALL_RETURN (::asctime (::localtime (t)), char *, 0); +#else + ACE_OSCALL_RETURN (::ctime (t), char *, 0); +#endif // ACE_HAS_BROKEN_CTIME) +} + +ACE_INLINE char * +ACE_OS::ctime_r (const time_t *t, char *buf, int buflen) +{ +// ACE_TRACE ("ACE_OS::ctime_r"); + char *result; +#if defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) +#if !defined (AIX) && !defined (UNIXWARE) + ACE_OSCALL (::ctime_r (t, buf, buflen), char *, 0, result); +#elif defined (ACE_HAS_ONLY_TWO_PARAMS_FOR_ASCTIME_R_AND_CTIME_R) + char *result; + ACE_OSCALL (::ctime_r (t, buf), char *, 0, result); + ::strncpy (buf, result, TIMELEN); + return buf; +#else + ACE_OSCALL (::ctime_r (t, buf), char *, 0, result); +#endif /* !defined (AIX) */ +#else + ACE_OSCALL (::ctime (t), char *, 0, result); +#endif + ::strncpy (buf, result, buflen); + return buf; +} + +ACE_INLINE struct tm * +ACE_OS::localtime (const time_t *t) +{ +// ACE_TRACE ("ACE_OS::localtime"); + ACE_OSCALL_RETURN (::localtime (t), struct tm *, 0); +} + +ACE_INLINE struct tm * +ACE_OS::localtime_r (const time_t *t, struct tm *res) +{ +// ACE_TRACE ("ACE_OS::localtime_r"); +#if defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) + ACE_OSCALL_RETURN (::localtime_r (t, res), struct tm *, 0); +#else + ACE_OSCALL_RETURN (::localtime (t), struct tm *, 0); +#endif +} + +ACE_INLINE char * +ACE_OS::asctime (const struct tm *t) +{ +// ACE_TRACE ("ACE_OS::asctime"); + ACE_OSCALL_RETURN (::asctime (t), char *, 0); +} + +ACE_INLINE char * +ACE_OS::asctime_r (const struct tm *t, char *buf, int buflen) +{ +// ACE_TRACE ("ACE_OS::asctime_r"); +#if defined (ACE_HAS_REENTRANT_FUNCTIONS) && defined (ACE_MT_SAFE) +#if !defined (AIX) && !defined (UNIXWARE) + ACE_OSCALL_RETURN (::asctime_r (t, buf, buflen), char *, 0); +#elif defined (ACE_HAS_ONLY_TWO_PARAMS_FOR_ASCTIME_R_AND_CTIME_R) + char *result; + ACE_OSCALL (::asctime_r (t, buf), char *, 0, result); + ::strncpy (buf, result, TIMELEN); + return buf; +#else + ACE_OSCALL_RETURN (::asctime_r (t, buf), char *, 0); +#endif /* !defined (AIX) */ +#else + ACE_OSCALL_RETURN (::asctime (t), char *, 0); +#endif +} + +ACE_INLINE int +ACE_OS::flock_init (ACE_OS::flock_t *lock, + int flags, + LPCTSTR name, + mode_t perms) +{ +// ACE_TRACE ("ACE_OS::flock_init"); +#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 = INVALID_HANDLE_VALUE; +#endif /* ACE_WIN32 */ + lock->handle_ = ACE_INVALID_HANDLE; + + if (name != 0) + { + ACE_OSCALL (ACE_OS::open (name, flags, perms), + ACE_HANDLE, + ACE_INVALID_HANDLE, + lock->handle_); + return lock->handle_ == ACE_INVALID_HANDLE ? -1 : 0; + } + else + return 0; +} + +ACE_INLINE int +ACE_OS::flock_wrlock (ACE_OS::flock_t *lock, short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_OS::flock_wrlock"); +#if defined (ACE_WIN32) + lock->overlapped_.Offset = start; + if (len == 0) + len = ::GetFileSize (lock->handle_, NULL); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, LOCKFILE_EXCLUSIVE_LOCK, 0, len, 0, &lock->overlapped_), + _result), int, -1); +#elif defined (VXWORKS) + 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 (::fcntl (lock->handle_, F_SETLKW, &lock->lock_), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_rdlock (ACE_OS::flock_t *lock, short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_OS::flock_rdlock"); +#if defined (ACE_WIN32) + lock->overlapped_.Offset = start; + if (len == 0) + len = ::GetFileSize (lock->handle_, NULL); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, 0, 0, len, 0, &lock->overlapped_), + _result), int, -1); +#elif defined (VXWORKS) + 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 (::fcntl (lock->handle_, F_SETLKW, &lock->lock_), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_trywrlock (ACE_OS::flock_t *lock, short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_OS::flock_trywrlock"); +#if defined (ACE_WIN32) + lock->overlapped_.Offset = start; + if (len == 0) + len = ::GetFileSize (lock->handle_, NULL); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, 0, len, 0, &lock->overlapped_), + _result), int, -1); +#elif defined (VXWORKS) + 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 + + // Does not block, if no access, returns -1. + ACE_OSCALL_RETURN (::fcntl (lock->handle_, F_SETLK, &lock->lock_), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_tryrdlock (ACE_OS::flock_t *lock, short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_OS::flock_tryrdlock"); +#if defined (ACE_WIN32) + lock->overlapped_.Offset = start; + if (len == 0) + len = ::GetFileSize (lock->handle_, NULL); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, LOCKFILE_FAIL_IMMEDIATELY, 0, len, 0, &lock->overlapped_), + _result), int, -1); +#elif defined (VXWORKS) + 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 + + // Does not block, if no access, returns -1. + ACE_OSCALL_RETURN (::fcntl (lock->handle_, F_SETLK, &lock->lock_), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_unlock (ACE_OS::flock_t *lock, short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_OS::flock_unlock"); +#if defined (ACE_WIN32) + lock->overlapped_.Offset = start; + if (len == 0) + len = ::GetFileSize (lock->handle_, NULL); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::UnlockFileEx (lock->handle_, 0, len, 0, &lock->overlapped_), + _result), int, -1); +#elif defined (VXWORKS) + 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 (::fcntl (lock->handle_, F_SETLK, &lock->lock_), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_destroy (ACE_OS::flock_t *lock) +{ +// ACE_TRACE ("ACE_OS::flock_destroy"); + if (lock->handle_ != ACE_INVALID_HANDLE) + { + ACE_OS::flock_unlock (lock); + ACE_OS::close (lock->handle_); + lock->handle_ = ACE_INVALID_HANDLE; + } + return 0; +} + +ACE_INLINE int +ACE_OS::execv (const char *path, char *const argv[]) +{ +// ACE_TRACE ("ACE_OS::execv"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::execv (path, argv), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::execve (const char *path, char *const argv[], char *const envp[]) +{ +// ACE_TRACE ("ACE_OS::execve"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::execvp (const char *file, char *const argv[]) +{ +// ACE_TRACE ("ACE_OS::execvp"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::execvp (file, argv), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::execl (const char *path, const char *arg0, ...) +{ +// ACE_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 */ +} + +ACE_INLINE int +ACE_OS::execle (const char *path, const char *arg0, ...) +{ +// ACE_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 */ +} + +ACE_INLINE int +ACE_OS::execlp (const char *file, const char *arg0, ...) +{ +// ACE_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 */ +} + +ACE_INLINE FILE * +ACE_OS::fdopen (ACE_HANDLE handle, const char *mode) +{ +// ACE_TRACE ("ACE_OS::fdopen"); +#if 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) + { + file = ::_fdopen (crt_handle, mode); + + if (!file) + ::_close (crt_handle); + } + + return file; +#else + ACE_OSCALL_RETURN (::fdopen (handle, mode), FILE *, 0); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::ftruncate (ACE_HANDLE handle, off_t offset) +{ +// ACE_TRACE ("ACE_OS::ftruncate"); +#if defined (ACE_WIN32) + if (::SetFilePointer (handle, offset, NULL, FILE_BEGIN) != -1) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SetEndOfFile (handle), _result), int, -1); + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +#else + ACE_OSCALL_RETURN (::ftruncate (handle, offset), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::getrlimit (int resource, struct rlimit *rl) +{ +// ACE_TRACE ("ACE_OS::getrlimit"); + +#if defined (ACE_WIN32) || defined (ACE_LACKS_RLIMIT) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::getrlimit (resource, rl), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::setrlimit (int resource, ACE_SETRLIMIT_TYPE *rl) +{ +// ACE_TRACE ("ACE_OS::setrlimit"); + +#if defined (ACE_WIN32) || defined (ACE_LACKS_RLIMIT) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::setrlimit (resource, rl), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::socketpair (int domain, int type, + int protocol, ACE_HANDLE sv[2]) +{ +// ACE_TRACE ("ACE_OS::socketpair"); +#if defined (ACE_WIN32) || defined (ACE_LACKS_SOCKETPAIR) + 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_TRACE ("ACE_OS::dup"); +#if defined (ACE_WIN32) + 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) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::dup (handle), ACE_HANDLE, ACE_INVALID_HANDLE); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::dup2 (ACE_HANDLE oldhandle, ACE_HANDLE newhandle) +{ +// ACE_TRACE ("ACE_OS::dup2"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::dup2 (oldhandle, newhandle), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE hrtime_t +ACE_OS::gethrtime (void) +{ +// ACE_TRACE ("ACE_OS::gethrtime"); +#if defined (ACE_HAS_HI_RES_TIMER) + ACE_OSCALL_RETURN (::gethrtime (), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_HI_RES_TIMER */ +} + +ACE_INLINE int +ACE_OS::fdetach (const char *file) +{ +// ACE_TRACE ("ACE_OS::fdetach"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::fdetach (file), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::fattach (int handle, const char *path) +{ +// ACE_TRACE ("ACE_OS::fattach"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::fattach (handle, path), int, -1); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE pid_t +ACE_OS::fork (void) +{ +// ACE_TRACE ("ACE_OS::fork"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (pid_t (-1)); +#else + ACE_OSCALL_RETURN (::fork (), pid_t, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE pid_t +ACE_OS::getpid (void) +{ +// ACE_TRACE ("ACE_OS::getpid"); +#if defined (ACE_WIN32) + return ::GetCurrentProcessId(); +#elif defined (VXWORKS) + // getpid() is not supported: just one process anyways + return 0; +#else + ACE_OSCALL_RETURN (::getpid (), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE off_t +ACE_OS::lseek (ACE_HANDLE handle, off_t offset, int whence) +{ +// ACE_TRACE ("ACE_OS::lseek"); + +#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 */ + return ::SetFilePointer (handle, offset, NULL, whence); +#else + ACE_OSCALL_RETURN (::lseek (handle, offset, whence), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE pid_t +ACE_OS::wait (int *stat_loc) +{ +// ACE_TRACE ("ACE_OS::wait"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#else +#if !defined (AIX) +#if defined (ACE_HAS_UNION_WAIT) + ACE_OSCALL_RETURN (::wait ((union wait *) stat_loc), pid_t, -1); +#else + ACE_OSCALL_RETURN (::wait (stat_loc), pid_t, -1); +#endif /* ACE_HAS_UNION_WAIT */ +#else + ACE_OSCALL_RETURN (::wait ((union wait *) stat_loc), pid_t, -1); +#endif /* defined (AIX) */ +#endif /* defined (ACE_WIN32) */ +} + +ACE_INLINE pid_t +ACE_OS::waitpid (pid_t pid, int *stat_loc, int options) +{ +// ACE_TRACE ("ACE_OS::waitpid"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (0); +#else + ACE_OSCALL_RETURN (::waitpid (pid, stat_loc, options), + pid_t, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::ioctl (ACE_HANDLE handle, int cmd, void *val) +{ +// ACE_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) + // this may not work very well... + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::ioctl (handle, cmd, (int) val), _result), + int, ERROR); +#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_TRACE ("ACE_OS::kill"); +#if defined (ACE_WIN32) + // Create a handle for the given process id. + ACE_HANDLE process_handle = + ::OpenProcess (PROCESS_ALL_ACCESS, + FALSE, // New handle is not inheritable. + pid); + + if (process_handle == ACE_INVALID_HANDLE) + return -1; + else + { + // Kill the process associated with process_handle. + BOOL terminate_result = ::TerminateProcess (process_handle, 0); + // Free up the kernel resources. + ACE_OS::close (process_handle); + return terminate_result; + } +#else + ACE_OSCALL_RETURN (::kill (pid, signum), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::sigaction (int signum, + const struct sigaction *nsa, + struct sigaction *osa) +{ +// ACE_TRACE ("ACE_OS::sigaction"); +#if defined (ACE_WIN32) + struct sigaction sa; + + if (osa == 0) + osa = &sa; + + osa->sa_handler = ::signal (signum, nsa->sa_handler); + return osa->sa_handler == SIG_ERR ? -1 : 0; +#elif defined (ACE_LACKS_POSIX_PROTO) + ACE_OSCALL_RETURN (::sigaction (signum, (struct sigaction*) nsa, osa), int, -1); +#else + ACE_OSCALL_RETURN (::sigaction (signum, nsa, osa), int, -1); +#endif /* ACE_LACKS_POSIX_PROTO */ +} + +ACE_INLINE char * +ACE_OS::getcwd (char *buf, size_t size) +{ +// ACE_TRACE ("ACE_OS::getcwd"); +#if defined (ACE_WIN32) + return ::_getcwd (buf, size); +#else + ACE_OSCALL_RETURN (::getcwd (buf, size), char *, 0); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::sleep (u_int seconds) +{ +// ACE_TRACE ("ACE_OS::sleep"); +#if defined (ACE_WIN32) + ::Sleep (seconds * 1000); + return 0; +#elif defined (VXWORKS) + 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, NULL), 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_TRACE ("ACE_OS::sleep"); +#if defined (ACE_WIN32) + ::Sleep (tv.msec ()); + return 0; +#elif defined (ACE_HAS_POLL) + ACE_OSCALL_RETURN (::poll (0, 0, tv.msec ()), int, -1); +#else + ACE_OSCALL_RETURN (::select (0, 0, 0, 0, (timeval *) &tv), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE char * +ACE_OS::getenv (const char *symbol) +{ +// ACE_TRACE ("ACE_OS::getenv"); + ACE_OSCALL_RETURN (::getenv (symbol), char *, 0); +} + +ACE_INLINE +ACE_Str_Buf::ACE_Str_Buf (void *b, int l, int max) + : buf (b), + len (l), + maxlen (max) +{ +} + +#if defined (ACE_HAS_UNICODE) + +ACE_INLINE wchar_t * +ACE_OS::strcat (wchar_t *s, const wchar_t *t) +{ +// ACE_TRACE ("ACE_OS::strcat"); + return ::wcscat (s, t); +} + +#if 0 +ACE_INLINE wchar_t * +ACE_OS::strstr (const wchar_t *s, const wchar_t *t) +{ +// ACE_TRACE ("ACE_OS::strstr"); + return ::wcsstr (s, t); +} + +ACE_INLINE wchar_t * +ACE_OS::strdup (const wchar_t *s) +{ +// ACE_TRACE ("ACE_OS::strdup"); + return ::wcsdup (s); +} +#endif /* 0 */ + +ACE_INLINE wchar_t * +ACE_OS::strchr (const wchar_t *s, int c) +{ +// ACE_TRACE ("ACE_OS::strchr"); + return ::wcschr (s, c); +} + +ACE_INLINE wchar_t * +ACE_OS::strrchr (const wchar_t *s, int c) +{ +// ACE_TRACE ("ACE_OS::strrchr"); + return ::wcsrchr (s, c); +} + +ACE_INLINE int +ACE_OS::strcmp (const wchar_t *s, const wchar_t *t) +{ +// ACE_TRACE ("ACE_OS::strcmp"); + return ::wcscmp (s, t); +} + +ACE_INLINE wchar_t * +ACE_OS::strcpy (wchar_t *s, const wchar_t *t) +{ +// ACE_TRACE ("ACE_OS::strcpy"); + return ::wcscpy (s, t); +} + +ACE_INLINE size_t +ACE_OS::strlen (const wchar_t *s) +{ +// ACE_TRACE ("ACE_OS::strlen"); + return ::wcslen (s); +} + +ACE_INLINE int +ACE_OS::strncmp (const wchar_t *s, const wchar_t *t, size_t len) +{ +// ACE_TRACE ("ACE_OS::strncmp"); + return ::wcsncmp (s, t, len); +} + +ACE_INLINE wchar_t * +ACE_OS::strncpy (wchar_t *s, const wchar_t *t, size_t len) +{ +// ACE_TRACE ("ACE_OS::strncpy"); + return ::wcsncpy (s, t, len); +} + +ACE_INLINE wchar_t * +ACE_OS::strtok (wchar_t *s, const wchar_t *tokens) +{ +// ACE_TRACE ("ACE_OS::strtok"); + return ::wcstok (s, tokens); +} + +ACE_INLINE long +ACE_OS::strtol (const wchar_t *s, wchar_t **ptr, int base) +{ +// ACE_TRACE ("ACE_OS::strtol"); + return ::wcstol (s, ptr, base); +} +#endif /* ACE_HAS_UNICODE */ diff --git a/ace/Obstack.cpp b/ace/Obstack.cpp new file mode 100644 index 00000000000..5bd969201bb --- /dev/null +++ b/ace/Obstack.cpp @@ -0,0 +1,119 @@ +// Obstack.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Obstack.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_Obstack) + +void +ACE_Obstack::dump (void) const +{ + ACE_TRACE ("ACE_Obstack::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "size_ = %d\n", this->size_)); + ACE_DEBUG ((LM_DEBUG, "head_ = %x\n", this->head_)); + ACE_DEBUG ((LM_DEBUG, "curr_ = %x\n", this->curr_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Obchunk) + +void +ACE_Obchunk::dump (void) const +{ + ACE_TRACE ("ACE_Obchunk::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "end_ = %x\n", this->end_)); + ACE_DEBUG ((LM_DEBUG, "cur_ = %x\n", this->cur_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +class ACE_Obchunk * +ACE_Obstack::new_chunk (void) +{ + ACE_TRACE ("ACE_Obstack::new_chunk"); + class ACE_Obchunk *temp = (class ACE_Obchunk *) + new char[sizeof (class ACE_Obchunk) + this->size_]; + + if (temp == 0) + { + errno = ENOMEM; + return 0; + } + + temp->next_ = 0; + temp->end_ = temp->contents_ + this->size_; + temp->cur_ = temp->contents_; + + return temp; +} + +ACE_Obstack::ACE_Obstack (int sz) + : size_ (sz), + head_ (0) +{ + ACE_TRACE ("ACE_Obstack::ACE_Obstack"); + this->head_ = this->new_chunk (); + this->curr_ = this->head_; +} + +ACE_Obstack::~ACE_Obstack (void) +{ + ACE_TRACE ("ACE_Obstack::~ACE_Obstack"); + class ACE_Obchunk *temp = this->head_; + + while (temp != 0) + { + class ACE_Obchunk *next = temp->next_; + temp->next_ = 0; + delete [] temp; + temp = next; + } +} + +char * +ACE_Obstack::copy (const char *s, + size_t len) +{ + ACE_TRACE ("ACE_Obstack::copy"); + char *result; + + ACE_ASSERT (this->size_ >= len + 1); + + // Check whether we need to grow our chunk... + + if (this->curr_->cur_ + len + 1 >= this->curr_->end_) + { + // Check whether we can just reuse previously allocated memory. + + if (this->curr_->next_ == 0) + { + this->curr_->next_ = this->new_chunk (); + this->curr_ = this->curr_->next_; + } + else + { + this->curr_ = this->curr_->next_; + this->curr_->cur_ = this->curr_->contents_; + } + } + + result = this->curr_->cur_; + ACE_OS::memcpy (result, s, len); + result[len] = '\0'; + this->curr_->cur_ += (len + 1); + return result; +} + +void +ACE_Obstack::release (void) +{ + ACE_TRACE ("ACE_Obstack::release"); + this->curr_ = this->head_; + this->curr_->cur_ = this->curr_->contents_; +} + + diff --git a/ace/Obstack.h b/ace/Obstack.h new file mode 100644 index 00000000000..91540994bc2 --- /dev/null +++ b/ace/Obstack.h @@ -0,0 +1,79 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Obstack.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_OBSTACK_H) +#define ACE_OBSTACK_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Obchunk + // = TITLE + // A "chunk" of memory. This should be a nested class but some + // compilers don't like them yet. +{ +friend class ACE_Obstack; + +public: + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + char *end_; + char *cur_; + ACE_Obchunk *next_; + char contents_[4]; +}; + +class ACE_Export ACE_Obstack + // = TITLE + // Define a simple "mark and release" memory allocation utility. + // This class is based on the GNU obstack utility. +{ +public: + // = Initialization and termination methods. + ACE_Obstack (int size = 4080); + ~ACE_Obstack (void); + + char *copy (const char* data, size_t len); + // Copy the data into the current Obchunk. + + void release (void); + // "Release" the entire stack (without freeing it). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + class ACE_Obchunk *new_chunk (void); + + size_t size_; + // Current size of the Obstack; + + class ACE_Obchunk *head_; + // Head of the Obchunk chain. + + class ACE_Obchunk *curr_; + // Pointer to the current Obchunk. +}; + +#endif /* ACE_OBSTACK_H */ diff --git a/ace/Obstack.i b/ace/Obstack.i new file mode 100644 index 00000000000..893b926ad3a --- /dev/null +++ b/ace/Obstack.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Obstack.i diff --git a/ace/Parse_Node.cpp b/ace/Parse_Node.cpp new file mode 100644 index 00000000000..e22f2969944 --- /dev/null +++ b/ace/Parse_Node.cpp @@ -0,0 +1,545 @@ +// Parse_Node.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Service_Config.h" +#include "ace/Service_Repository.h" +#include "ace/Task.h" +#include "ace/Parse_Node.h" + +// Provide the class hierarchy that defines the parse tree of Service +// Nodes. + +#if !defined (__ACE_INLINE__) +#include "ace/Parse_Node.i" +#endif /* ____ */ + +// Keeps track of the number of errors encountered so far. +extern int ace_yyerrno; + +// Global variable used to communicate between the parser and the main +// program. +extern ACE_Service_Config *ace_this_svc; + +ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Node) + +void +ACE_Stream_Node::dump (void) const +{ + ACE_TRACE ("ACE_Stream_Node::dump"); +} + +void +ACE_Stream_Node::apply (void) +{ + ACE_TRACE ("ACE_Stream_Node::apply"); + + if (ACE_Service_Config::initialize (this->node_->record (), + this->node_->parameters ()) == -1) + ace_yyerrno++; + + ACE_DEBUG ((LM_DEBUG, "did stream on %s, error = %d\n", + this->node_->name (), + ace_yyerrno)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Parse_Node) + +void +ACE_Parse_Node::dump (void) const +{ + ACE_TRACE ("ACE_Parse_Node::dump"); +} + +const char * +ACE_Parse_Node::name (void) const +{ + ACE_TRACE ("ACE_Parse_Node::name"); + return this->name_; +} + +ACE_Parse_Node * +ACE_Parse_Node::link (void) const +{ + ACE_TRACE ("ACE_Parse_Node::link"); + return this->next_; +} + +void +ACE_Parse_Node::link (ACE_Parse_Node *n) +{ + ACE_TRACE ("ACE_Parse_Node::link"); + this->next_ = n; +} + +ACE_Stream_Node::ACE_Stream_Node (const ACE_Static_Node *str_ops, + const ACE_Parse_Node *str_mods) + : node_ (str_ops), + mods_ (str_mods), + ACE_Parse_Node (str_ops->name ()) +{ + ACE_TRACE ("ACE_Stream_Node::ACE_Stream_Node"); +} + + +ACE_Stream_Node::~ACE_Stream_Node (void) +{ + ACE_TRACE ("ACE_Stream_Node::~ACE_Stream_Node"); + delete (ACE_Static_Node *) this->node_; + delete (ACE_Parse_Node *) this->mods_; +} + +ACE_Parse_Node::ACE_Parse_Node (void) + : next_ (0) +{ + ACE_TRACE ("ACE_Parse_Node::ACE_Parse_Node"); +} + + +ACE_Parse_Node::ACE_Parse_Node (const char *nm) + : name_ (nm), + next_ (0) +{ + ACE_TRACE ("ACE_Parse_Node::ACE_Parse_Node"); +} + +void +ACE_Parse_Node::print (void) const +{ + ACE_TRACE ("ACE_Parse_Node::print"); + ACE_DEBUG ((LM_DEBUG, "svc = %s\n", this->name ())); + if (this->next_) + this->next_->print (); +} + + +ACE_Parse_Node::~ACE_Parse_Node (void) +{ + ACE_TRACE ("ACE_Parse_Node::~ACE_Parse_Node"); + delete this->next_; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Suspend_Node) + +void +ACE_Suspend_Node::dump (void) const +{ + ACE_TRACE ("ACE_Suspend_Node::dump"); +} + +ACE_Suspend_Node::ACE_Suspend_Node (const char *name) + : ACE_Parse_Node (name) +{ + ACE_TRACE ("ACE_Suspend_Node::ACE_Suspend_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Resume_Node) + +void +ACE_Resume_Node::dump (void) const +{ + ACE_TRACE ("ACE_Resume_Node::dump"); +} + +ACE_Resume_Node::ACE_Resume_Node (const char *name) + : ACE_Parse_Node (name) +{ + ACE_TRACE ("ACE_Resume_Node::ACE_Resume_Node"); +} + +void +ACE_Suspend_Node::apply (void) +{ + ACE_TRACE ("ACE_Suspend_Node::apply"); + if (ACE_Service_Config::suspend (this->name ()) == -1) + ace_yyerrno++; + + ACE_DEBUG ((LM_DEBUG, "did suspend on %s, error = %d\n", + this->name (), ace_yyerrno)); +} + +void +ACE_Resume_Node::apply (void) +{ + ACE_TRACE ("ACE_Resume_Node::apply"); + if (ACE_Service_Config::resume (this->name ()) == -1) + ace_yyerrno++; + + ACE_DEBUG ((LM_DEBUG, "did resume on %s, error = %d\n", + this->name (), ace_yyerrno)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Remove_Node) + +void +ACE_Remove_Node::dump (void) const +{ + ACE_TRACE ("ACE_Remove_Node::dump"); +} + +ACE_Remove_Node::ACE_Remove_Node (const char *name) + : ACE_Parse_Node (name) +{ + ACE_TRACE ("ACE_Remove_Node::ACE_Remove_Node"); +} + +void +ACE_Remove_Node::apply (void) +{ + ACE_TRACE ("ACE_Remove_Node::apply"); + if (ACE_Service_Config::remove (this->name ()) == -1) + ace_yyerrno++; + + ACE_DEBUG ((LM_DEBUG, "did remove on %s, error = %d\n", + this->name (), ace_yyerrno)); + +} + + +ACE_Dynamic_Node::ACE_Dynamic_Node (const ACE_Service_Record *sr, + char *parms) + : record_ (sr), + ACE_Static_Node (sr->name (), parms) +{ + ACE_TRACE ("ACE_Dynamic_Node::ACE_Dynamic_Node"); +} + +const ACE_Service_Record * +ACE_Dynamic_Node::record (void) const +{ + ACE_TRACE ("ACE_Dynamic_Node::record"); + return this->record_; +} + +void +ACE_Dynamic_Node::apply (void) +{ + ACE_TRACE ("ACE_Dynamic_Node::apply"); + if (ACE_Service_Config::initialize (this->record (), + this->parameters ()) == -1) + ace_yyerrno++; + + ACE_DEBUG ((LM_DEBUG, "did dynamic on %s, error = %d\n", + this->name (), ace_yyerrno)); + +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Dynamic_Node) + +void +ACE_Dynamic_Node::dump (void) const +{ + ACE_TRACE ("ACE_Dynamic_Node::dump"); +} + +ACE_Dynamic_Node::~ACE_Dynamic_Node (void) +{ + ACE_TRACE ("ACE_Dynamic_Node::~ACE_Dynamic_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Static_Node) + +void +ACE_Static_Node::dump (void) const +{ + ACE_TRACE ("ACE_Static_Node::dump"); +} + +ACE_Static_Node::ACE_Static_Node (const char *nm, + char *params) + : ACE_Parse_Node (nm), + parameters_ (params) +{ + ACE_TRACE ("ACE_Static_Node::ACE_Static_Node"); +} + +const ACE_Service_Record * +ACE_Static_Node::record (void) const +{ + ACE_TRACE ("ACE_Static_Node::record"); + ACE_Service_Record *sr; + + if (ACE_Service_Config::svc_rep ()->find (this->name (), + (const ACE_Service_Record **) &sr) == -1) + return 0; + else + return sr; +} + +char * +ACE_Static_Node::parameters (void) const +{ + ACE_TRACE ("ACE_Static_Node::parameters"); + return this->parameters_; +} + +void +ACE_Static_Node::apply (void) +{ + ACE_TRACE ("ACE_Static_Node::apply"); + if (ACE_Service_Config::initialize (this->name (), + this->parameters ()) == -1) + ace_yyerrno++; + + ACE_DEBUG ((LM_DEBUG, "did static on %s, error = %d\n", + this->name (), ace_yyerrno)); +} + + +ACE_Static_Node::~ACE_Static_Node (void) +{ + ACE_TRACE ("ACE_Static_Node::~ACE_Static_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Location_Node) + +void +ACE_Location_Node::dump (void) const +{ + ACE_TRACE ("ACE_Location_Node::dump"); +} + +ACE_Location_Node::ACE_Location_Node (void) + : handle_ (0), + symbol_ (0), + pathname_ (0) +{ + ACE_TRACE ("ACE_Location_Node::ACE_Location_Node"); +} + +ACE_Location_Node::~ACE_Location_Node (void) +{ + ACE_TRACE ("ACE_Location_Node::~ACE_Location_Node"); +} + +const char * +ACE_Location_Node::pathname (void) const +{ + ACE_TRACE ("ACE_Location_Node::pathname"); + return this->pathname_; +} + +void +ACE_Location_Node::pathname (const char *p) +{ + ACE_TRACE ("ACE_Location_Node::pathname"); + this->pathname_ = p; +} + +void +ACE_Location_Node::handle (const void *h) +{ + ACE_TRACE ("ACE_Location_Node::handle"); + this->handle_ = h; +} + +const void * +ACE_Location_Node::handle (void) const +{ + ACE_TRACE ("ACE_Location_Node::handle"); + return this->handle_; +} + +void +ACE_Location_Node::set_symbol (const void *s) +{ + ACE_TRACE ("ACE_Location_Node::set_symbol"); + this->symbol_ = s; +} + +int +ACE_Location_Node::dispose (void) const +{ + ACE_TRACE ("ACE_Location_Node::dispose"); + return this->must_delete_; +} + +const void * +ACE_Location_Node::open_handle (void) +{ + ACE_TRACE ("ACE_Location_Node::open_handle"); + + char dl_pathname[MAXPATHLEN]; + + // Transform the pathname into the appropriate dynamic link library + // by searching the ACE_LD_SEARCH_PATH. + ACE::ldfind (this->pathname (), dl_pathname, sizeof dl_pathname); + + this->handle (ACE_OS::dlopen (dl_pathname, RTLD_LAZY)); + + if (this->handle () == 0) + { + ace_yyerrno++; + + ACE_ERROR ((LM_ERROR, "dlopen failed for %s", dl_pathname)); + + char *errmsg = ACE_OS::dlerror (); + + if (errmsg != 0) + ACE_ERROR_RETURN ((LM_ERROR, ": %s\n", errmsg), 0); + else + ACE_ERROR_RETURN ((LM_ERROR, "\n"), 0); + } + else + return this->handle (); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Object_Node) + +void +ACE_Object_Node::dump (void) const +{ + ACE_TRACE ("ACE_Object_Node::dump"); +} + +ACE_Object_Node::ACE_Object_Node (const char *path, + const char *obj_name) + : object_name_ (obj_name) +{ + ACE_TRACE ("ACE_Object_Node::ACE_Object_Node"); + this->pathname (path); + this->must_delete_ = 0; +} + +const void * +ACE_Object_Node::symbol (void) +{ + ACE_TRACE ("ACE_Object_Node::symbol"); + if (this->open_handle () != 0) + { + this->symbol_ = (const void *) + ACE_OS::dlsym ((void *) this->handle (), (char *) this->object_name_); + + if (this->symbol_ == 0) + { + ace_yyerrno++; + + ACE_ERROR ((LM_ERROR, + "dlsym failed for object %s", + this->object_name_)); + + char *errmsg = ACE_OS::dlerror (); + + if (errmsg != 0) + ACE_ERROR_RETURN ((LM_ERROR, ": %s\n", errmsg), 0); + else + ACE_ERROR_RETURN ((LM_ERROR, "\n"), 0); + } + } + return this->symbol_; +} + +ACE_Object_Node::~ACE_Object_Node (void) +{ + ACE_TRACE ("ACE_Object_Node::~ACE_Object_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Function_Node) + +void +ACE_Function_Node::dump (void) const +{ + ACE_TRACE ("ACE_Function_Node::dump"); +} + +ACE_Function_Node::ACE_Function_Node (const char *path, + const char *func_name) + : function_name_ (func_name) +{ + ACE_TRACE ("ACE_Function_Node::ACE_Function_Node"); + this->pathname (path); + this->must_delete_ = 1; +} + +const void * +ACE_Function_Node::symbol (void) +{ + ACE_TRACE ("ACE_Function_Node::symbol"); + if (this->open_handle () != 0) + { + const void *(*func) (void) = 0; + this->symbol_ = 0; + + // Locate the factory function <function_name> in the shared + // object. + + func = (const void *(*)(void)) + ACE_OS::dlsym ((void *) this->handle (), + (ACE_DL_TYPE) this->function_name_); + + if (func == 0) + { + ace_yyerrno++; + + if (this->symbol_ == 0) + { + ace_yyerrno++; + + ACE_ERROR ((LM_ERROR, "dlsym failed for function %s", + this->function_name_)); + + char *errmsg = ACE_OS::dlerror (); + + if (errmsg != 0) + ACE_ERROR_RETURN ((LM_ERROR, ": %s\n", errmsg), 0); + else + ACE_ERROR_RETURN ((LM_ERROR, "\n"), 0); + } + } + // Invoke the factory function and record it's return value. + this->symbol_ = (*func) (); + + if (this->symbol_ == 0) + { + ace_yyerrno++; + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", this->function_name_), 0); + } + } + return this->symbol_; +} + +ACE_Function_Node::~ACE_Function_Node (void) +{ + ACE_TRACE ("ACE_Function_Node::~ACE_Function_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Dummy_Node) + +void +ACE_Dummy_Node::dump (void) const +{ + ACE_TRACE ("ACE_Dummy_Node::dump"); +} + +ACE_Dummy_Node::ACE_Dummy_Node (const ACE_Static_Node *static_node, + const ACE_Parse_Node *str_mods) + : node_ (static_node), + mods_ (str_mods), + ACE_Parse_Node (static_node->name ()) +{ + ACE_TRACE ("ACE_Dummy_Node::ACE_Dummy_Node"); +} + +void +ACE_Dummy_Node::apply (void) +{ + ACE_TRACE ("ACE_Dummy_Node::apply"); + ACE_DEBUG ((LM_DEBUG, "did operations on stream %s, error = %d\n", + this->name (), ace_yyerrno)); +} + +ACE_Dummy_Node::~ACE_Dummy_Node (void) +{ + ACE_TRACE ("ACE_Dummy_Node::~ACE_Dummy_Node"); + delete (ACE_Static_Node *) this->node_; + delete (ACE_Parse_Node *) this->mods_; +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +#if defined (ACE_HAS_THREADS) +// template class ACE_Message_Queue<ACE_Thread_Mutex, ACE_Condition_Thread_Mutex>; +// template class ACE_Task<ACE_Thread_Mutex, ACE_Condition_Thread_Mutex>; +// template class ACE_Task_Exit<ACE_Thread_Mutex, ACE_Condition_Thread_Mutex>; +// template class ACE_TSS<ACE_Task_Exit<ACE_Thread_Mutex, ACE_Condition_Thread_Mutex> >; +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Parse_Node.h b/ace/Parse_Node.h new file mode 100644 index 00000000000..9423a7d5af8 --- /dev/null +++ b/ace/Parse_Node.h @@ -0,0 +1,256 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Parse_Node.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_PARSE_NODE_H) +#define ACE_PARSE_NODE_H + +#include "ace/Service_Record.h" + +class ACE_Export ACE_Parse_Node + // = TITLE + // Provide the base of the object hierarchy that defines the parse + // tree of Service Nodes. +{ +public: + ACE_Parse_Node (void); + ACE_Parse_Node (const char *name); + virtual ~ACE_Parse_Node (void); + + ACE_Parse_Node *link (void) const; + void link (ACE_Parse_Node *); + virtual void apply (void) = 0; + + const char *name (void) const; + void print (void) const; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const char *name_; + ACE_Parse_Node *next_; +}; + +class ACE_Export ACE_Suspend_Node : public ACE_Parse_Node + // = TITLE + // Suspend a Service Node. +{ +public: + ACE_Suspend_Node (const char *name); + + virtual void apply (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Resume_Node : public ACE_Parse_Node + // = TITLE + // Resume a Service Node. +{ +public: + ACE_Resume_Node (const char *name); + + virtual void apply (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Remove_Node : public ACE_Parse_Node + // = TITLE + // Remove a Service Node. +{ +public: + ACE_Remove_Node (const char *name); + + virtual void apply (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Static_Node : public ACE_Parse_Node + // = TITLE + // Handle a statically linked node. +{ +public: + ACE_Static_Node (const char *name, char *params = 0); + virtual ~ACE_Static_Node (void); + + virtual void apply (void); + virtual const ACE_Service_Record *record (void) const; + char *parameters (void) const; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + char *parameters_; +}; + +class ACE_Export ACE_Dynamic_Node : public ACE_Static_Node + // = TITLE + // Handle a dynamically linked node. +{ +public: + ACE_Dynamic_Node (const ACE_Service_Record *, char *params); + virtual ~ACE_Dynamic_Node (void); + + virtual const ACE_Service_Record *record (void) const; + virtual void apply (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const ACE_Service_Record *record_; +}; + +class ACE_Export ACE_Stream_Node : public ACE_Parse_Node + // = TITLE + // Handle a Stream. +{ +public: + ACE_Stream_Node (const ACE_Static_Node *, const ACE_Parse_Node *); + virtual ~ACE_Stream_Node (void); + + virtual void apply (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const ACE_Static_Node *node_; + const ACE_Parse_Node *mods_; +}; + +class ACE_Export ACE_Location_Node + // = TITLE + // Keep track of where a shared library is located. +{ +public: + ACE_Location_Node (void); + virtual const void *symbol (void) = 0; + virtual void set_symbol (const void *h); + const void *handle (void) const; + void handle (const void *h); + const char *pathname (void) const; + void pathname (const char *h); + int dispose (void) const; + + virtual ~ACE_Location_Node (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + const void *open_handle (void); + + const void *handle_; + const void *symbol_; + const char *pathname_; + int must_delete_; +}; + +class ACE_Export ACE_Object_Node : public ACE_Location_Node + // = TITLE + // Keeps track of the symbol name for a shared object. +{ +public: + ACE_Object_Node (const char *pathname, const char *obj_name); + virtual const void *symbol (void); + virtual ~ACE_Object_Node (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const char *object_name_; +}; + +class ACE_Export ACE_Function_Node : public ACE_Location_Node + // = TITLE + // Keeps track of the symbol name of for a shared function. +{ +public: + ACE_Function_Node (const char *pathname, const char *func_name); + virtual const void *symbol (void); + virtual ~ACE_Function_Node (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const char *function_name_; +}; + +class ACE_Export ACE_Dummy_Node : public ACE_Parse_Node + // = TITLE + // I forget why this is here... ;-) +{ +public: + ACE_Dummy_Node (const ACE_Static_Node *, const ACE_Parse_Node *); + ~ACE_Dummy_Node (void); + virtual void apply (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const ACE_Static_Node *node_; + const ACE_Parse_Node *mods_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Parse_Node.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_PARSE_NODE_H */ diff --git a/ace/Parse_Node.i b/ace/Parse_Node.i new file mode 100644 index 00000000000..84c7266d734 --- /dev/null +++ b/ace/Parse_Node.i @@ -0,0 +1,6 @@ +/* -*- C++ -*- */ +// $Id$ + +// Parse_Node.i + + diff --git a/ace/Pipe.cpp b/ace/Pipe.cpp new file mode 100644 index 00000000000..31ab6d95d85 --- /dev/null +++ b/ace/Pipe.cpp @@ -0,0 +1,132 @@ +// Pipe.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/SOCK_Acceptor.h" +#include "ace/SOCK_Connector.h" +#include "ace/Pipe.h" + +void +ACE_Pipe::dump (void) const +{ + ACE_TRACE ("ACE_Pipe::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "handles_[0] = %d", this->handles_[0])); + ACE_DEBUG ((LM_DEBUG, "\nhandles_[1] = %d", this->handles_[1])); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_Pipe::open (void) +{ + ACE_TRACE ("ACE_Pipe::open"); +#if defined (ACE_WIN32) || defined (ACE_LACKS_SOCKETPAIR) + ACE_INET_Addr my_addr; + ACE_SOCK_Acceptor acceptor; + ACE_SOCK_Connector connector; + ACE_SOCK_Stream reader; + ACE_SOCK_Stream writer; + int result = 0; + + // Bind listener to any port. + if (acceptor.open (ACE_Addr::sap_any) == -1) + result = -1; + else if (acceptor.get_local_addr (my_addr) == -1) + result = -1; + else + { + 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) + result = -1; + else if (acceptor.accept (reader) == -1) + { + writer.close (); + result = -1; + } + } + + // Close down the acceptor endpoint since we don't need it anymore. + acceptor.close (); + if (result == -1) + return -1; + + this->handles_[0] = reader.get_handle (); + this->handles_[1] = writer.get_handle (); + +#elif defined (ACE_HAS_STREAM_PIPES) + if (ACE_OS::pipe (this->handles_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "pipe"), -1); + + int arg = RMSGN; + + // Enable "msg no discard" mode, which ensures that record + // boundaries are maintained when messages are sent and received. + if (ACE_OS::ioctl (this->handles_[0], I_SRDOPT, (void *) arg) == -1 + || ACE_OS::ioctl (this->handles_[1], I_SRDOPT, (void *) arg) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ioctl"), -1); +#else + if (ACE_OS::socketpair (AF_UNIX, SOCK_DGRAM, 0, this->handles_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "socketpair"), -1); +#endif /* ACE_WIN32 */ + // Point both the read and write HANDLES to the appropriate socket + // HANDLEs. + + return 0; +} + +int +ACE_Pipe::open (ACE_HANDLE handles[2]) +{ + ACE_TRACE ("ACE_Pipe::open"); + + if (this->open () == -1) + return -1; + else + { + handles[0] = this->handles_[0]; + handles[1] = this->handles_[1]; + return 0; + } +} + +// Do nothing... + +ACE_Pipe::ACE_Pipe (void) +{ + ACE_TRACE ("ACE_Pipe::ACE_Pipe"); + + this->handles_[0] = ACE_INVALID_HANDLE; + this->handles_[1] = ACE_INVALID_HANDLE; +} + +ACE_Pipe::ACE_Pipe (ACE_HANDLE handles[2]) +{ + ACE_TRACE ("ACE_Pipe::ACE_Pipe"); + + if (this->open (handles) == -1) + ACE_ERROR ((LM_ERROR, "ACE_Pipe::ACE_Pipe")); +} + +ACE_Pipe::ACE_Pipe (ACE_HANDLE read, + ACE_HANDLE write) +{ + ACE_TRACE ("ACE_Pipe::ACE_Pipe"); + this->handles_[0] = read; + this->handles_[1] = write; +} + +int +ACE_Pipe::close (void) +{ + ACE_TRACE ("ACE_Pipe::close"); + + if (ACE_OS::close (this->handles_[0]) == -1 + || ACE_OS::close (this->handles_[1]) == -1) + return -1; + else + return 0; +} diff --git a/ace/Pipe.h b/ace/Pipe.h new file mode 100644 index 00000000000..485e1133f87 --- /dev/null +++ b/ace/Pipe.h @@ -0,0 +1,73 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Pipe.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_PIPE_H) +#define ACE_PIPE_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Pipe + // = TITLE + // Provides a bidirectional "pipe" abstraction that is portable + // to Windows NT, SVR4 UNIX, and BSD UNIX. + // + // = DESCRIPTION + // Uses "name" for lookup in the ACE service repository. Obtains + // the object and returns it as the appropriate type. +{ +public: + // = Initialization and termination. + ACE_Pipe (void); + // Default constructor (does nothing...). + + ACE_Pipe (ACE_HANDLE handles[2]); + // Open the pipe and initialize the handles. + + ACE_Pipe (ACE_HANDLE read, ACE_HANDLE write); + // Initialize the <ACE_Pipe> from the <read> and <write> handles. + + int open (ACE_HANDLE handles[2]); + // Open the pipe and initialize the handles. + + int open (void); + // Open the pipe. + + int close (void); + // Close down the pipe HANDLEs; + + // = Accessors. + + ACE_HANDLE read_handle (void); + // This is the "read" side of the pipe. Note, however, that + // processes can also write to this handle as well since pipes are + // bi-directional. + + ACE_HANDLE write_handle (void); + // This is the "write" side of the pipe. Note, however, that + // processes can also read to this handle as well since pipes are + // bi-directional. + + void dump (void) const; + // Dump the state of the object. + +private: + ACE_HANDLE handles_[2]; +}; + +#include "ace/Pipe.i" + +#endif /* ACE_PIPE_H */ diff --git a/ace/Pipe.i b/ace/Pipe.i new file mode 100644 index 00000000000..3808263eb18 --- /dev/null +++ b/ace/Pipe.i @@ -0,0 +1,18 @@ +/* -*- C++ -*- */ +// $Id$ + +// Pipe.i + +inline ACE_HANDLE +ACE_Pipe::read_handle (void) +{ + ACE_TRACE ("ACE_Pipe::read_handle"); + return this->handles_[0]; +} + +inline ACE_HANDLE +ACE_Pipe::write_handle (void) +{ + ACE_TRACE ("ACE_Pipe::write_handle"); + return this->handles_[1]; +} diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp new file mode 100644 index 00000000000..54379d8a28c --- /dev/null +++ b/ace/Proactor.cpp @@ -0,0 +1,536 @@ +// Proactor.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Proactor.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Proactor.i" +#endif /* __ACE_INLINE__ */ + +class ACE_Overlapped_IO : public ACE_OVERLAPPED + // = TITLE + // A wrapper for Win32 OVERLAPPED. + // + // = DESCRIPTION + // Acts as a magic cookie storing additional state associated + // with overlapped I/O operations. ReadFile and WriteFile take + // OVERLAPPED, so we pass in Overlapped_IO. OVERLAPPEDs are + // returned through GetQueuedCompletionStatus. They are cast + // back into Overlapped_IOs to get the handler_ etc. +{ +public: + // = Initialization and termination methods. + ACE_Overlapped_IO (ACE_Reactor_Mask mask, + ACE_Event_Handler *handler, + ACE_Message_Block *message, + ACE_Overlapped_File *file, + ACE_HANDLE event_handle); + + ~ACE_Overlapped_IO (void); + // Death. + + int dispatch (u_long bytes_transfered); + // Callback the appropriate handle_* method on handler_. + + int initiate (u_long &bytes_transfered); + // Call ReadFile or Writefile. + + operator ACE_OVERLAPPED * (void); + // Return this. + + void re_init (void); + // Reset the object to be reused. Calls get_message on the handler_ + // for a new message. + + ACE_Reactor_Mask mask_; + // Reading or writing. + ACE_Event_Handler *handler_; + // The IO handler. + ACE_Message_Block *message_; + // The current message to send/recv. + ACE_Overlapped_File *file_; + // The optional file pointer to update. + +private: + void init (void); + // Reset everything. +}; + +ACE_Overlapped_IO::ACE_Overlapped_IO (ACE_Reactor_Mask mask, + ACE_Event_Handler *handler, + ACE_Message_Block *message, + ACE_Overlapped_File *file, + ACE_HANDLE event_handle) + : mask_ (mask), + handler_ (handler), + message_ (message), + file_ (file) +{ + this->hEvent = event_handle; + this->init (); +} + +void +ACE_Overlapped_IO::init (void) +{ + if (file_ == 0) + this->Offset = 0; + else + this->Offset = file_->offset (); + + this->Internal = 0; + this->InternalHigh = 0; + this->OffsetHigh = 0; +} + +void +ACE_Overlapped_IO::re_init (void) +{ + this->message_ = this->handler_->get_message (); + + this->init (); +} + +ACE_Overlapped_IO::~ACE_Overlapped_IO (void) +{ +} + +int +ACE_Overlapped_IO::dispatch (u_long bytes_transfered) +{ + if (this->file_ != 0) + // Move the file pointer forward. + file_->lseek (bytes_transfered, SEEK_CUR); + + if (this->mask_ == ACE_Event_Handler::WRITE_MASK) + { + // Update the message length to reflect what was sent. + this->message_->rd_ptr (bytes_transfered); + return handler_->handle_output_complete (this->message_, + bytes_transfered); + } + else // this->mask_ == ACE_Event_Handler::READ_MASK + { + // Update the message length to reflect what was received. + this->message_->wr_ptr (bytes_transfered); + return this->handler_->handle_input_complete (this->message_, + bytes_transfered); + } +} + +// When we port this to use Posix async I/O, these calls will be +// replace will generic ACE_OS calls. + +int +ACE_Overlapped_IO::initiate (u_long &bytes_transfered) +{ +#if defined (ACE_WIN32) + if (this->mask_ == ACE_Event_Handler::WRITE_MASK) + { + // Try to write. + return ::WriteFile (this->handler_->get_handle (), + this->message_->rd_ptr (), + this->message_->length (), + &bytes_transfered, + this); + } + else + { + // READ_MASK is set, so try to read. + return ::ReadFile (this->handler_->get_handle (), + this->message_->wr_ptr (), + this->message_->size (), + &bytes_transfered, + this); + } +#else + ACE_NOTSUP_RETURN (-1); +#endif +} + +ACE_Overlapped_IO::operator ACE_OVERLAPPED * (void) +{ + return (ACE_OVERLAPPED *) this; +} + +ACE_Proactor::ACE_Proactor (size_t number_of_threads) + : completion_port_ (0), + number_of_threads_ (number_of_threads), + timer_skew_ (0, ACE_TIMER_SKEW) +{ +#if defined (ACE_WIN32) + // Create an "auto-reset" event to indicate that one or more I/O + // overlapped events have completed. + this->global_handle_ = ::CreateEvent (NULL, TRUE, FALSE, NULL); +#endif /* ACE_HAS_WIN32 */ +} + +int +ACE_Proactor::close (void) +{ + if (this->completion_port_ != 0) + ACE_OS::close (this->completion_port_); + + ACE_OS::close (this->global_handle_); + return 0; +} + +int +ACE_Proactor::handle_signal (int index, siginfo_t *, ucontext_t *) +{ + ACE_TRACE ("ACE_Proactor::handle_signal"); + + ACE_Time_Value timeout (0, 0); + +#if defined (ACE_WIN32) + // Reset the handle to a non-signaled state. + if (::ResetEvent (global_handle_) == FALSE) + ACE_ERROR_RETURN ((LM_ERROR, "ResetEvent failed.\n"), -1); +#endif /* ACE_HAS_WIN32 */ + + // Perform a non-blocking "poll" for all the I/O events that have + // completed in the I/O completion queue. + + int result; + + while ((result = this->handle_events (&timeout)) == 1) + continue; + + // If our handle_events failed, we'll report a failure to the + // ReactorEx. + return result == -1 ? -1 : 0; +} + + +int +ACE_Proactor::schedule_timer (ACE_Event_Handler *handler, + const void *arg, + const ACE_Time_Value &delta_time, + const ACE_Time_Value &interval) +{ + ACE_TRACE ("ACE_Proactor::schedule_timer"); + + return this->timer_queue_.schedule + (handler, arg, ACE_OS::gettimeofday () + delta_time, interval); +} + +int +ACE_Proactor::handle_events (ACE_Time_Value *how_long) +{ + // Stash the current time. + ACE_Time_Value prev_time = ACE_OS::gettimeofday (); + + how_long = timer_queue_.calculate_timeout (how_long); + + ACE_Overlapped_IO *overlapped = 0; + u_long bytes_transfered = 0; + +#if defined (ACE_WIN32) + int error = 0; + ACE_HANDLE io_handle = ACE_INVALID_HANDLE; + + // When we port this to use Posix async I/O, this call will be + // replace will a generic ACE_OS call. + BOOL result; + + result = ::GetQueuedCompletionStatus (this->completion_port_, + &bytes_transfered, + (u_long *) &io_handle, + (ACE_OVERLAPPED **) &overlapped, + how_long == 0 ? INFINITE : how_long->msec ()); + + // Check for a failed dequeue. Stash the error value. + if (result == FALSE && overlapped == 0) + error = ::GetLastError (); + + // Check for any timers that can be handled before we dispatch the + // dequeued event. Note that this is done irrespective of whether + // an error occurred. + if (!this->timer_queue_.is_empty ()) + // Fudge factor accounts for problems with Solaris timers... + this->timer_queue_.expire (ACE_OS::gettimeofday () + this->timer_skew_); + + // @@ Need to make sure that if GetQueuedCompletionStatus fails due + // to a time out that this information is propagated correctly to + // the caller! + + // GetQueued returned because of a error or timer. + if (error != 0) + { + // Compute the time while the Proactor is processing. + ACE_Time_Value elapsed_time = ACE_OS::gettimeofday () - prev_time; + + // Update -how_long- to reflect the amount of time since + // handle_events was called. + if (how_long != 0) + { + if (*how_long > elapsed_time) + *how_long = *how_long - elapsed_time; + else + *how_long = ACE_Time_Value::zero; // Used all of timeout. + } + + // @@ What's the WIN32 constant for 258?!?!?! + if (error == 258) + // Returning because of timeout. + return 0; + // Returning because of error. + ACE_ERROR_RETURN ((LM_ERROR, + "%p GetQueuedCompletionStatus failed errno = %d.\n" + "ACE_Proactor::handle_events", error), -1); + } + +#endif /* ACE_WIN32 */ + + // Dequeued a failed or successful operation. Dispatch the + // Event_Handler. Note that GetQueuedCompletionStatus returns false + // when operations fail, but they still need to be dispatched. + // Should we propogate this to the handler somehow? Maybe an extra + // failed/succeeded flag in the dispatch call? + int dispatch_result = this->dispatch (overlapped, bytes_transfered); + + // Compute the time while the Proactor is processing. + ACE_Time_Value elapsed_time = ACE_OS::gettimeofday () - prev_time; + + // Update <how_long> to reflect the amount of time since + // <handle_events> was called. + if (how_long != 0) + { + if (*how_long > elapsed_time) + *how_long = *how_long - elapsed_time; + else + *how_long = ACE_Time_Value::zero; // Used all of timeout. + } + + // Return -1 (failure), or return 1. Remember that 0 is reserved + // for timeouts only, so we have to turn dispatch_results to 1. So, + // if this->dispatch() returns a 1 or 0, we return 1. Otherwise, + // we return -1. + return dispatch_result == -1 ? -1 : 1; +} + +// Returns 0 or 1 on success, -1 on failure. +int +ACE_Proactor::dispatch (ACE_Overlapped_IO *overlapped, + u_long bytes_transfered) +{ + // Call back the Event_Handler and do what it wants based on the + // return value. + int dispatch_result = overlapped->dispatch (bytes_transfered); + + switch (dispatch_result) + { + case 1: // Start another operation. + // Reinitialize by getting a new message and resetting the + // overlapped offset. + overlapped->re_init (); + return this->initiate (overlapped); + case -1: // Handler is closing. + overlapped->handler_-> + handle_close (overlapped->handler_->get_handle (), + overlapped->mask_); + // Fallthrough. + default: + // Handler succeeded, but does not want another operation + // started. + delete overlapped; + return 0; + } +} + +// Returns 0 or 1 on success, -1 on failure. +int +ACE_Proactor::initiate (ACE_Event_Handler *handler, + ACE_Reactor_Mask mask, + ACE_Message_Block *msg, + ACE_Overlapped_File *file) +{ + if (msg == 0) + msg = handler->get_message (); + + // Create the state for this operation. This object "is-a" + // OVERLAPPED structure, and holds other data and methods for this + // operation. + ACE_Overlapped_IO *overlapped; + + ACE_NEW_RETURN (overlapped, + ACE_Overlapped_IO (mask, handler, msg, + file, this->global_handle_), + -1); + + return this->initiate (overlapped); +} + +// Returns 0 or 1 on success, -1 on failure. +// Returns 1 when initiate succeeded immediately. +int +ACE_Proactor::initiate (ACE_Overlapped_IO *overlapped) +{ +#if defined (ACE_WIN32) + u_long bytes_transfered = 0; + + ACE_HANDLE io_handle = overlapped->handler_->get_handle (); + ACE_HANDLE cp; + + cp = ::CreateIoCompletionPort (io_handle, + this->completion_port_, + (u_long) io_handle, + this->number_of_threads_); + + if (cp != 0) + // Success. + this->completion_port_ = cp; + else // Failure. + { + int error = ::GetLastError (); + // If errno == ERROR_INVALID_PARAMETER, then this handle was + // already registered. + if (error != ERROR_INVALID_PARAMETER) + ACE_ERROR_RETURN ((LM_ERROR, + "%p CreateIoCompletionPort failed errno = %d.\n", + "ACE_Proactor::initiate", error), -1); + } + + // Initiate a WriteFile/ReadFile. If it succeeds, dispatch the + // handler. + int initiate_result = overlapped->initiate (bytes_transfered); + + if (initiate_result) + // Return 1; the OVERLAPPED will still get queued. + return 1; + + // If initiate failed, check for a bad error. + int err = ::GetLastError (); + switch (err) + { + case ERROR_HANDLE_EOF: + case ERROR_NETNAME_DELETED: + // The OVERLAPPED will *not* get queued for this case. Thus, we + // have to dispatch immediately. + return this->dispatch (overlapped, bytes_transfered); + + case ERROR_IO_PENDING: + // The IO will complete proactively. + return 0; + default: + // This is a *bad* error. + ACE_ERROR ((LM_ERROR, "I/O error %d\n", err)); + return -1; + } +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_Overlapped_File::ACE_Overlapped_File (const ACE_Overlapped_File &file) + : offset_ (file.offset ()), + handle_ (file.get_handle ()), + file_size_ (0), + delete_handle_ (0) +{ +} + +ACE_Overlapped_File::ACE_Overlapped_File (void) + : offset_ (0), + handle_ (ACE_INVALID_HANDLE), + file_size_ (0), + delete_handle_ (0) +{ +} + +ACE_Overlapped_File::ACE_Overlapped_File (const char *file_name, + int mode, + int perms) + : delete_handle_ (1) +{ + this->open (file_name, mode, perms); +} + +ACE_Overlapped_File::~ACE_Overlapped_File (void) +{ + this->close (); +} + +void +ACE_Overlapped_File::close (void) +{ + if (this->handle_ != ACE_INVALID_HANDLE + && this->delete_handle_ != 0) + { + ACE_OS::close (this->handle_); + this->handle_ = ACE_INVALID_HANDLE; + } +} + +int +ACE_Overlapped_File::open (ACE_HANDLE handle) +{ + this->handle_ = handle; + this->delete_handle_ = 0; + + if (this->handle_ == ACE_INVALID_HANDLE) + return -1; + else + return 0; +} + +int +ACE_Overlapped_File::open (const char *file_name, + int access, + int share, + LPSECURITY_ATTRIBUTES security, + int creation, + int flags, + ACE_HANDLE template_file) +{ +#if defined (ACE_WIN32) + if (file_name != 0) + this->handle_ = ::CreateFile (file_name, access, share, + security, creation, flags, + template_file); + + if (this->handle_ == ACE_INVALID_HANDLE) + { + errno = ENOENT; + return -1; + } + else + { + this->delete_handle_ = 1; + return 0; + } +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +off_t +ACE_Overlapped_File::lseek (off_t offset, + int whence) +{ + switch (whence) + { + case SEEK_SET: + this->offset_ = offset; + break; + case SEEK_CUR: + this->offset_ += offset; + break; + case SEEK_END: + if (handle_ == ACE_INVALID_HANDLE) + { + errno = ENFILE; + return -1; + } + else + this->offset_ = ACE_OS::filesize (handle_) + offset; + break; + default : + errno = EINVAL; + ACE_ERROR_RETURN ((LM_ERROR, "ACE_Overlapped_File::lseek" + "Invalid whence = %d.\n"), -1); + } + + return this->offset_; +} diff --git a/ace/Proactor.h b/ace/Proactor.h new file mode 100644 index 00000000000..8fb845b0f3e --- /dev/null +++ b/ace/Proactor.h @@ -0,0 +1,256 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Proactor.h +// +// = AUTHOR +// Doug Schmidt (schmidt@cs.wustl.edu), +// Tim Harrison (harrison@cs.wustl.edu), and +// Irfan Pyarali (ip1@cs.wustl.edu). +// +// ============================================================================ + +#if !defined (ACE_Proactor_H) +#define ACE_Proactor_H + +#include "ace/OS.h" +#include "ace/Message_Block.h" +#include "ace/Timer_Queue.h" +#include "ace/Event_Handler.h" + +// Forward declaration. +class ACE_Overlapped_File; + +// Cheshire cat declaration (meow). +class ACE_Overlapped_IO; + +class ACE_Export ACE_Proactor : public ACE_Event_Handler +// = TITLE +// An abstraction for Proactive I/O. +// +// = DESCRIPTION +// +// The ACE_Proactor encapsulates Win32 overlapped I/O. The ACE_Proactor +// is also an ACE_Event_Handler which can be registered with the +// ACE_ReactorEx, as follows: +// +// int +// main () +// { +// // ... +// +// // Register Proactor with ReactorEx. +// ACE_Service_Config::reactorEx ()->register_handler +// (ACE_Service_Config::proactor ()); +// +// // Demultiplex all ReactorEx and Proactor events from a single +// // thread. +// ACE_Service_Config::run_reactorEx_event_loop (); +// +// return 42; +// } +// +// This makes it possible to seemlessly integrate the ACE_Proactor (which +// handles only overlapped I/O) with other forms of Win32 HANDLE-based +// synchronization (e.g., Mutexes, Semaphores, Threads, Processes, etc.). +{ +public: + // = Initialization and termination methods. + + ACE_Proactor (size_t number_of_threads = 0); + // Initialize a proactor and give it the number of threads to allow + // to run concurrently (note that we don't spawn the threads, the NT + // kernel does). + + int close (void); + // Close completion port. + + // = Event demultiplexing hooks inherited from Event_Handler. + virtual int handle_signal (int, siginfo_t * = 0, ucontext_t * = 0); + // Called back when used in the context of the ReactorEx. + + virtual ACE_HANDLE get_handle (void) const; + // Returns the underlying Win32 Event HANDLE that is used to + // integrate I/O completion ports with the ReactorEx. + + // = Event loop methods. + virtual int handle_events (ACE_Time_Value *how_long = 0); + virtual int handle_events (ACE_Time_Value &how_long); + // Main event loop driver that blocks for -how_long- before + // returning (will return earlier if I/O or signal events occur). + // Note that -how_long- can be 0, in which case this method blocks + // until I/O events or signals occur. handle_events just blocks + // on GetQueuedCompletionStatus at completion_port_. When I/O + // completions arrive, it calls back the Event_Handler associated + // with completed I/O operation. Returns 0 if -how_long- elapses + // before an event occurs, 1 when if an event occured, and -1 on + // failure. + + // = Communication method. + virtual int initiate (ACE_Event_Handler *handler, + ACE_Reactor_Mask mask = ACE_Event_Handler::WRITE_MASK, + ACE_Message_Block *msg = 0, + ACE_Overlapped_File *file = 0); + // Invoke proactive I/O on <handler>. If <msg> == 0, the Proactor + // will call handler::get_message to obtain an ACE_Message_Block + // to send/recv according to <mask>. If <mask> == + // ACE_Event_Handler::WRITE_MASK, the Proactor calls WriteFile using + // the <msg> and Event_Handler::get_handle. Returns 1 if the operation + // succeeded immediately, 0 if the operation is pending (in which + // case the <handler> will be called back), and -1 if an error + // occurred. <file> represents the offset into the file to initiate + // the operation with. When using the proactor for overlapped file + // I/O, the user is responsible for maintaining the pointer to the + // file. If you perform multiple initiates with the same or no + // File_Pointer value, initiate will fill in the same file data into + // multiple Message_Blocks. <file> is ignored for network I/O or if + // <file> == 0. If <file> != 0 it is updated (via lseek) respective to + // the operation initiated. + + // = Timer management. + virtual int schedule_timer (ACE_Event_Handler *, + const void *arg, + const ACE_Time_Value &delta, + const ACE_Time_Value &interval = ACE_Time_Value::zero); + // Schedule an <Event_Handler> that will expire after <delay> amount + // of time. If it expires then <arg> is passed in as the value to + // the <Event_Handler>'s <handle_timeout> callback method. If + // <interval> is != to <ACE_Time_Value::zero> then it is used to + // reschedule the <Event_Handler> automatically. This method + // returns a timer handle that uniquely identifies the + // <Event_Handler> in an internal list. This timer handle can be + // used to cancel an <Event_Handler> before it expires. The + // cancellation ensures that timer_ids are unique up to values of + // greater than 2 billion timers. As long as timers don't stay + // around longer than this there should be no problems with + // accidentally deleting the wrong timer. + + virtual int cancel_timer (ACE_Event_Handler *handler); + // Cancel all <Event_Handlers> that match the address of + // <Event_Handler>. + + virtual int cancel_timer (int timer_id, const void **arg = 0); + // Cancel the single <ACE_Event_Handler> that matches the <timer_id> + // value (which was returned from the <schedule> method). If arg is + // non-NULL then it will be set to point to the ``magic cookie'' + // argument passed in when the <Event_Handler> was registered. This + // makes it possible to free up the memory and avoid memory leaks. + +protected: + + ACE_Timer_Queue timer_queue_; + // Maintains the list of pending timers. + + ACE_Time_Value timer_skew_; + // Adjusts for timer skew in various clocks. + + virtual int initiate (ACE_Overlapped_IO *overlapped); + // Helper to initiate. + + int dispatch (ACE_Overlapped_IO *overlapped, + u_long bytes_transfered); + // Helper function which dispatches results to Event_Handlers. + + ACE_HANDLE completion_port_; + // The completion_port_ is where <handler> should tell a completed + // I/O operation to queue up. All proactive I/O operation + // completions queue up on this handle. This handle is set by the + // <invoke> method. + + size_t number_of_threads_; + // Max threads that will be allowed to run in a completion port. + + ACE_HANDLE global_handle_; + // Win32 HANDLE associated with every operation that signals when + // any operation completes (used to transparently integrate the + // <ACE_Proactor> with the <ACE_Dispatcher>). +}; + +class ACE_Export ACE_Overlapped_File + // = TITLE + // A wrapper for overlapped file I/O. + // + // = DESCRIPTION + // ACE_Overlapped_File is place-holder for file I/O. When + // performing overlapped I/O in win32, a file pointer is not + // managed by the kernel. Instead, the user is responsible for + // maintaining file pointers for all open files. This wrapper + // provides an abstraction for a file pointer. The Proactor + // updates Overlapped_File objects when overlapped I/O operations + // complete. Eventually, this class may be integrated with + // ACE_FILE_IO. +{ +public: + // = Initialization and termination methods. + ACE_Overlapped_File (void); + // Open must be called. + + ACE_Overlapped_File (const ACE_Overlapped_File &file); + // Copy <file>. + + ACE_Overlapped_File (const char *file_name, int mode, int perms = 0); + // Construction of an ACE_Overlapped_File. Calls open. + + ~ACE_Overlapped_File (void); + // Destruction. Calls close. + + int open (const char *file_name, + int access = GENERIC_READ, + int share = FILE_SHARE_READ, + LPSECURITY_ATTRIBUTES security = 0, + int creation = OPEN_EXISTING, + int flags = FILE_ATTRIBUTE_NORMAL, + ACE_HANDLE template_file = ACE_INVALID_HANDLE); + // Opens <file_name> according to <mode> and <perms>. This method + // is equivalent to CreateFile. Returns 0 on success, -1 on failure + // with errno == reason. + + int open (ACE_HANDLE handle); + // Uses the given <handle>. Returns 0 on success, -1 on failure. + // This will only return -1 when <handle> == ACE_INVALID_HANDLE. + + void close (void); + // Closes the file if open. Can be called explicitly, or implicitly + // through the destructor. + + off_t offset (void) const; + // Return the current offset into the file. + + off_t size (void) const; + // Return the current size of the file. + + off_t lseek (off_t offset, int whence); + // If <whence> == SEEK_SET, then the file pointer is set to + // <offset>. If <whence> == SEEK_CUR, then the file pointer is set + // to its current location plus <offset>. If <whence> == SEEK_END, + // the file pointer is set to the size of the file plus <offset>. + + ACE_HANDLE get_handle (void) const; + // Get the handle to the file. + +protected: + off_t offset_; + // Current offset into the file. + + off_t file_size_; + // Size of the file. + + ACE_HANDLE handle_; + // Handle to the I/O device. + + int delete_handle_; + // Keeps track of whether we need to delete the <handle_>. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Proactor.i" +#endif /* __ACE_INLINE__ */ +#endif /* ACE_Proactor_H */ + diff --git a/ace/Proactor.i b/ace/Proactor.i new file mode 100644 index 00000000000..fe58070da78 --- /dev/null +++ b/ace/Proactor.i @@ -0,0 +1,54 @@ +/* -*- C++ -*- */ +// $Id$ + + +ACE_INLINE off_t +ACE_Overlapped_File::offset (void) const +{ + ACE_TRACE ("ACE_Overlapped_File::offset"); + return this->offset_; +} + +ACE_INLINE off_t +ACE_Overlapped_File::size (void) const +{ + ACE_TRACE ("ACE_Overlapped_File::size"); + return ACE_OS::filesize (this->handle_); +} + +ACE_INLINE ACE_HANDLE +ACE_Overlapped_File::get_handle (void) const +{ + ACE_TRACE ("ACE_Overlapped_File::get_handle"); + return this->handle_; +} + +ACE_INLINE int +ACE_Proactor::cancel_timer (ACE_Event_Handler *handler) +{ + ACE_TRACE ("ACE_Proactor::cancel_timer"); + return this->timer_queue_.cancel (handler); +} + +ACE_INLINE int +ACE_Proactor::cancel_timer (int timer_id, + const void **arg) +{ + ACE_TRACE ("ACE_Proactor::cancel_timer"); + return this->timer_queue_.cancel (timer_id, arg); +} + +ACE_INLINE ACE_HANDLE +ACE_Proactor::get_handle (void) const +{ + ACE_TRACE ("ACE_Proactor::get_handle"); + + return this->global_handle_; +} + +ACE_INLINE int +ACE_Proactor::handle_events (ACE_Time_Value &how_long) +{ + return this->handle_events (&how_long); +} + diff --git a/ace/Process.cpp b/ace/Process.cpp new file mode 100644 index 00000000000..c2aa3ba9a84 --- /dev/null +++ b/ace/Process.cpp @@ -0,0 +1,197 @@ +#define ACE_BUILD_DLL +// $Id$ + +#include "ace/Process.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Process.i" +#endif /* __ACE_INLINE__ */ + +int +ACE_Process::wait (void) +{ +#if defined (ACE_WIN32) + return ::WaitForSingleObject (process_info_.hProcess, INFINITE); +#else /* ACE_WIN32 */ + return ACE_OS::waitpid (this->child_id_, 0, 0); +#endif /* ACE_WIN32 */ +} + +ACE_Process::ACE_Process (void) +#if defined (ACE_WIN32) + : set_handles_called_ (0) +#else /* ACE_WIN32 */ + : stdin_ (ACE_INVALID_HANDLE), + stdout_ (ACE_INVALID_HANDLE), + stderr_ (ACE_INVALID_HANDLE) +#endif /* ACE_WIN32 */ +{ +#if defined (ACE_WIN32) + ACE_OS::memset ((void *) &startup_info_, 0, sizeof startup_info_); + ACE_OS::memset ((void *) &process_info_, 0, sizeof process_info_); + startup_info_.cb = sizeof startup_info_; +#endif /* ACE_WIN32 */ +} + +ACE_Process::~ACE_Process (void) +{ +#if defined (ACE_WIN32) + // Just in case start wasn't called. + if (set_handles_called_) + { + ::CloseHandle (startup_info_.hStdInput); + ::CloseHandle (startup_info_.hStdOutput); + ::CloseHandle (startup_info_.hStdOutput); + set_handles_called_ = 0; + } + + // Free resources allocated in kernel. + ACE_OS::close (process_info_.hThread); + ACE_OS::close (process_info_.hProcess); + +#endif /* ACE_WIN32 */ +} + +int +ACE_Process::set_handles (ACE_HANDLE std_in, + ACE_HANDLE std_out, + ACE_HANDLE std_err) +{ +#if defined (ACE_WIN32) + set_handles_called_ = 1; + + // Tell the new process to use our std handles. + startup_info_.dwFlags = STARTF_USESTDHANDLES; + + if (std_in == ACE_INVALID_HANDLE) + std_in = ACE_STDIN; + if (std_out == ACE_INVALID_HANDLE) + std_out = ACE_STDOUT; + if (std_err == ACE_INVALID_HANDLE) + std_err = ACE_STDERR; + + if (!::DuplicateHandle (::GetCurrentProcess(), + std_in, + ::GetCurrentProcess(), + &startup_info_.hStdInput, + NULL, + TRUE, + DUPLICATE_SAME_ACCESS)) + return -1; + + if (!::DuplicateHandle (::GetCurrentProcess(), + std_out, + ::GetCurrentProcess(), + &startup_info_.hStdOutput, + NULL, + TRUE, + DUPLICATE_SAME_ACCESS)) + return -1; + + if (!::DuplicateHandle (::GetCurrentProcess(), + std_err, + ::GetCurrentProcess(), + &startup_info_.hStdError, + NULL, + TRUE, + DUPLICATE_SAME_ACCESS)) + return -1; +#else /* ACE_WIN32 */ + stdin_ = std_in; + stdout_ = std_out; + stderr_ = std_err; +#endif /* ACE_WIN32 */ + + return 0; // Success. +} + +int +ACE_Process::start (char *argv[]) +{ +#if defined (ACE_WIN32) + ACE_ARGV argv_buf (argv); + + char *buf = argv_buf.buf (); + + if (buf == 0) + return -1; + + BOOL fork_result = + ::CreateProcess (NULL, + buf, + NULL, // No process attributes. + NULL, // No thread attributes. + TRUE, // Allow handle inheritance. + NULL, // CREATE_NEW_CONSOLE, // Create a new console window. + NULL, // No environment. + NULL, // No current directory. + &startup_info_, + &process_info_); + + if (set_handles_called_) + { + ::CloseHandle (startup_info_.hStdInput); + ::CloseHandle (startup_info_.hStdOutput); + ::CloseHandle (startup_info_.hStdOutput); + set_handles_called_ = 0; + } + + if (fork_result) // If success. + return 0; + else + // CreateProcess failed. + return -1; +#else /* ACE_WIN32 */ + // Fork the new process. + this->child_id_ = ACE_OS::fork (); + + switch (this->child_id_) + { + case -1: + // Error. + return -1; + case 0: + if (stdin_ != ACE_INVALID_HANDLE + && ACE_OS::dup2 (stdin_, ACE_STDIN) == -1) + return -1; + else if (stdout_ != ACE_INVALID_HANDLE + && ACE_OS::dup2 (stdout_, ACE_STDOUT) == -1) + return -1; + else if (stderr_ != ACE_INVALID_HANDLE + && ACE_OS::dup2 (stderr_, ACE_STDERR) == -1) + return -1; + + // Child process executes the command. + if (ACE_OS::execv (argv[0], argv) == -1) + // If the execv fails, this child needs to exit. + ACE_OS::exit (errno); + default: + // Server process. The fork succeeded. + return 0; + } +#endif /* ACE_WIN32 */ +} + +ACE_Process::ACE_Process (char *argv[], + ACE_HANDLE std_in, + ACE_HANDLE std_out, + ACE_HANDLE std_err) +#if defined (ACE_WIN32) + : set_handles_called_ (0) +#else /* ACE_WIN32 */ + : stdin_ (ACE_INVALID_HANDLE), + stdout_ (ACE_INVALID_HANDLE), + stderr_ (ACE_INVALID_HANDLE) +#endif /* ACE_WIN32 */ +{ +#if defined (ACE_WIN32) + ACE_OS::memset ((void *) &startup_info_, 0, sizeof startup_info_); + ACE_OS::memset ((void *) &process_info_, 0, sizeof process_info_); + startup_info_.cb = sizeof startup_info_; +#endif /* ACE_WIN32 */ + + if (this->set_handles (std_in, std_out, std_err) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "set_handles")); + else if (this->start (argv) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "start")); +} diff --git a/ace/Process.h b/ace/Process.h new file mode 100644 index 00000000000..094fa78216d --- /dev/null +++ b/ace/Process.h @@ -0,0 +1,106 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Process.h +// +// = AUTHOR +// Tim Harrison <harrison@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_PROCESS_H) +#define ACE_PROCESS_H + +#include "ace/OS.h" +#include "ace/ARGV.h" +#include "ace/ACE.h" +#include "ace/Mem_Map.h" +#include "ace/Svc_Handler.h" +#include "ace/Synch.h" +#include "ace/Acceptor.h" +#include "ace/SOCK_Acceptor.h" + +class ACE_Export ACE_Process +// = TITLE +// A Portable encapsulation for creating new processes and +// allows assignment of STDIN, STDOUT, and STDERR of the new +// process. +// +// = DESCRIPTION +// On UNIX, ACE_Process uses fork and exec. On Win32, it uses +// CreateProcess. Since we can set the standard handles, we can +// mimic UNIX pipes on Win32 by building chains of processes. +// This class should be used instead ACE_OS::fork_exec. I'm +// implementing the functionality that I need as I go, instead of +// trying to build an all encompassing process abstraction. If +// anyone needs more functionality, please feel free to add it and +// send us the updates. We'll put it in ACE. +{ +public: + ACE_Process (void); + // Default construction. + + ACE_Process (char *argv[], + ACE_HANDLE std_in, + ACE_HANDLE std_out = ACE_INVALID_HANDLE, + ACE_HANDLE std_err = ACE_INVALID_HANDLE); + // Set the standard handles of the new process to the respective + // handles and 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 } Returns the + // new process id on success, -1 on failure. If you want to affect + // a subset of the handles, make sure to set the others to + // ACE_INVALID_HANDLE. + + ~ACE_Process (void); + // Death incarnate. + + int set_handles (ACE_HANDLE std_in, + ACE_HANDLE std_out = ACE_INVALID_HANDLE, + ACE_HANDLE std_err = ACE_INVALID_HANDLE); + // Set the standard handles of the new process to the respective + // handles. If you want to affect a subset of the handles, make + // sure to set the others to ACE_INVALID_HANDLE. Returns 0 on + // success, -1 on failure. + + int start (char *argv[]); + // 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 } Returns the new process id on success, -1 on + // failure. + + int wait (void); + // Wait for the process we just created to exit. + + int kill (int signum = SIGINT); + // Send the process a signal. + + pid_t getpid (void); + // Return the pid of the new process. + +private: +#if defined (ACE_WIN32) + PROCESS_INFORMATION process_info_; + STARTUPINFO startup_info_; + int set_handles_called_; + // Is 1 if stdhandles was called. +#else /* ACE_WIN32 */ + ACE_HANDLE stdin_; + ACE_HANDLE stdout_; + ACE_HANDLE stderr_; + pid_t child_id_; +#endif /* ACE_WIN32 */ +}; + +#if defined (__ACE_INLINE__) +#include "ace/Process.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_PROCESS_H */ diff --git a/ace/Process.i b/ace/Process.i new file mode 100644 index 00000000000..3e7dafb44d6 --- /dev/null +++ b/ace/Process.i @@ -0,0 +1,19 @@ +/* -*- C++ -*- */ +// $Id$ + + +ACE_INLINE pid_t +ACE_Process::getpid (void) +{ +#if defined (ACE_WIN32) + return process_info_.dwProcessId; +#else /* ACE_WIN32 */ + return child_id_; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_Process::kill (int signum) +{ + return ACE_OS::kill (this->getpid (), signum); +} diff --git a/ace/Process_Manager.cpp b/ace/Process_Manager.cpp new file mode 100644 index 00000000000..1ef354593f1 --- /dev/null +++ b/ace/Process_Manager.cpp @@ -0,0 +1,331 @@ +#if 0 +// $Id$ + +// Process_Manager.cpp +#define ACE_BUILD_DLL +#include "ace/Process_Manager.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Process_Manager.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Process_Control) +ACE_ALLOC_HOOK_DEFINE(ACE_Process_Manager) + +void +ACE_Process_Manager::dump (void) const +{ + ACE_TRACE ("ACE_Process_Manager::dump"); +} + +ACE_Process_Descriptor::ACE_Process_Descriptor (void) +{ + ACE_TRACE ("ACE_Process_Descriptor::ACE_Process_Descriptor"); +} + +int +ACE_Process_Manager::resize (size_t size) +{ + ACE_TRACE ("ACE_Process_Manager::resize"); + return -1; +} + +// Create and initialize the table to keep track of the process pool. + +int +ACE_Process_Manager::open (size_t size) +{ + ACE_TRACE ("ACE_Process_Manager::open"); + return -1; +} + +// Initialize the synchronization variables. + +ACE_Process_Manager::ACE_Process_Manager (size_t size) +{ + ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager"); +} + +// Close up and release all resources. + +int +ACE_Process_Manager::close (void) +{ + ACE_TRACE ("ACE_Process_Manager::close"); + return -1; +} + +ACE_Process_Manager::~ACE_Process_Manager (void) +{ + ACE_TRACE ("ACE_Process_Manager::~ACE_Process_Manager"); + 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; +} + +// 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_TRACE ("ACE_Process_Manager::spawn_n"); + return -1; +} + +// 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_TRACE ("ACE_Process_Manager::append_proc"); + + return -1; +} + +// Insert a process into the pool (checks for duplicates and doesn't +// allow them to be inserted twice). + +int +ACE_Process_Manager::insert_proc (pid_t t_id) +{ + ACE_TRACE ("ACE_Process_Manager::insert_proc"); + return -1; +} + +// Remove a process from the pool. Must be called with locks held. + +void +ACE_Process_Manager::remove_proc (int i) +{ + ACE_TRACE ("ACE_Process_Manager::remove_proc"); +} + +int +ACE_Process_Manager::resume_proc (int i) +{ + ACE_TRACE ("ACE_Process_Manager::resume_proc"); + return -1; +} + +int +ACE_Process_Manager::suspend_proc (int i) +{ + ACE_TRACE ("ACE_Process_Manager::suspend_proc"); + + return -1; +} + +int +ACE_Process_Manager::kill_proc (int i, int signum) +{ + ACE_TRACE ("ACE_Process_Manager::kill_proc"); + + return -1; +} + +// Locate the index in the table associated with <t_id>. Must be +// called with the lock held. + +int +ACE_Process_Manager::find (pid_t t_id) +{ + ACE_TRACE ("ACE_Process_Manager::find"); + return -1; +} + +// Suspend a single process. + +int +ACE_Process_Manager::suspend (pid_t t_id) +{ + ACE_TRACE ("ACE_Process_Manager::suspend"); + return -1; +} + +// Resume a single process. + +int +ACE_Process_Manager::resume (pid_t t_id) +{ + ACE_TRACE ("ACE_Process_Manager::resume"); + return -1; +} + +// Kill a single process. +int +ACE_Process_Manager::kill (pid_t t_id, int signum) +{ + ACE_TRACE ("ACE_Process_Manager::kill"); + return -1; +} + +// Get group ids for a particular process id. + +int +ACE_Process_Manager::get_grp (pid_t t_id, int &grp_id) +{ + ACE_TRACE ("ACE_Process_Manager::get_grp"); + return -1; +} + +// Set group ids for a particular process id. + +int +ACE_Process_Manager::set_grp (pid_t t_id, int grp_id) +{ + ACE_TRACE ("ACE_Process_Manager::set_grp"); + return -1; +} + +// Suspend a group of processs. + +int +ACE_Process_Manager::apply_grp (int grp_id, + PROC_FUNC func, + int arg) +{ + ACE_TRACE ("ACE_Process_Manager::apply_grp"); + return -1; +} + +int +ACE_Process_Manager::suspend_grp (int grp_id) +{ + ACE_TRACE ("ACE_Process_Manager::suspend_grp"); + return -1; +} + +// Resume a group of processs. + +int +ACE_Process_Manager::resume_grp (int grp_id) +{ + ACE_TRACE ("ACE_Process_Manager::resume_grp"); + return -1; +} + +// Kill a group of processs. + +int +ACE_Process_Manager::kill_grp (int grp_id, int signum) +{ + ACE_TRACE ("ACE_Process_Manager::kill_grp"); + return -1; +} + +int +ACE_Process_Manager::apply_all (PROC_FUNC func, int arg) +{ + ACE_TRACE ("ACE_Process_Manager::apply_all"); + return -1; +} + +// Resume all processs that are suspended. + +int +ACE_Process_Manager::resume_all (void) +{ + ACE_TRACE ("ACE_Process_Manager::resume_all"); + return -1; +} + +int +ACE_Process_Manager::suspend_all (void) +{ + ACE_TRACE ("ACE_Process_Manager::suspend_all"); + return -1; +} + +int +ACE_Process_Manager::kill_all (int sig) +{ + ACE_TRACE ("ACE_Process_Manager::kill_all"); + return -1; +} + +// Must be called when process goes out of scope to clean up its table +// slot. + +void * +ACE_Process_Manager::exit (void *status) +{ + ACE_TRACE ("ACE_Process_Manager::exit"); + return 0; +} + +// Wait for all the processs to exit. + +int +ACE_Process_Manager::wait (ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_Process_Manager::wait"); + return -1; +} + +void +ACE_Process_Control::dump (void) const +{ + ACE_TRACE ("ACE_Process_Control::dump"); +} + +// Initialize the process controller. + +ACE_Process_Control::ACE_Process_Control (ACE_Process_Manager *t, + int insert) +{ + ACE_TRACE ("ACE_Process_Control::ACE_Process_Control"); +} + +// Automatically kill process on exit. + +ACE_Process_Control::~ACE_Process_Control (void) +{ + ACE_TRACE ("ACE_Process_Control::~ACE_Process_Control"); +} + +// Exit from process (but clean up first). + +void * +ACE_Process_Control::exit (void *exit_status) +{ + ACE_TRACE ("ACE_Process_Control::exit"); + return 0; +} + +#endif diff --git a/ace/Process_Manager.h b/ace/Process_Manager.h new file mode 100644 index 00000000000..79d8c3b9c3d --- /dev/null +++ b/ace/Process_Manager.h @@ -0,0 +1,250 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Process_Manager.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_PROCESS_MANAGER_H) +#define ACE_PROCESS_MANAGER_H + +#include "ace/Log_Msg.h" +#include "ace/Synch.h" + +#if 0 +class ACE_Export ACE_Process_Descriptor + // = Title + // Information for controlling groups of processs. +{ +friend class ACE_Process_Manager; +public: + enum Process_State + { + IDLE, + SPAWNED, + RUNNING, + SUSPENDED, + TERMINATED + }; +private: + + ACE_Process_Descriptor (void); + + pid_t proc_id_; + // Unique process ID. + + int grp_id_; + // Unique group ID. + + Process_State proc_state_; + // Current state of the process. +}; + +// Forward declaration. + +class ACE_Process_Control; + +class ACE_Export ACE_Process_Manager + // = TITLE + // Manages a pool of processs. + // + // = DESCRIPTION + // This class allows operations on groups of processs atomically. +{ +friend class ACE_Process_Control; +public: + enum + { + DEFAULT_SIZE = 100 + }; + + // = Initialization and termination methods. + ACE_Process_Manager (size_t size = ACE_Process_Manager::DEFAULT_SIZE); + ~ACE_Process_Manager (void); + + int open (size_t size = DEFAULT_SIZE); + // Initialize the manager with room for SIZE processs. + + 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>. + + // 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>. + + // 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 + int kill (pid_t, int signum); + // Kill a single process. + int kill_grp (int grp_id, int signum); + // Kill a group of processs. + + // = Set/get group ids for a particular process id. + int set_grp (pid_t, int grp_id); + int get_grp (pid_t, int &grp_id); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +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>. + + int insert_proc (pid_t p_id); + // Insert a process in the table (checks for duplicates). + // Omitting the process handle won't work on Win32... + + int append_proc (pid_t p_id, ACE_Process_Descriptor::Process_State); + // Append a process in the table (adds at the end, growing the table + // if necessary). + + void remove_proc (int i); + // Remove process from the table. + + // = The following four methods implement a simple scheme for + // operating on a collection of processs atomically. + + typedef int (ACE_Process_Manager::*PROC_FUNC)(int, int); + + int apply_grp (int grp_id, PROC_FUNC, int = 0); + // Apply <func> to all members of the table that match the <grp_id>. + + 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>. + + ACE_Process_Descriptor *proc_table_; + // Vector that describes process state within the Process_Manager. + + size_t max_table_size_; + // Maximum number of processs we can manage (should be dynamically + // allocated). + + 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 + // = TITLE + // Used to keep track of a process's activities within its entry + // point function. +{ +public: + ACE_Process_Control (ACE_Process_Manager *tm, int insert = 0); + // Initialize the process control object. If INSERT != 0, then + // register the process with the ProcessManager. + + ~ACE_Process_Control (void); + // Implicitly kill the process on exit and remove it from its + // associated ProcessManager. + + void *exit (void *status); + // Explicitly kill the process on exit and remove it from its + // associated ProcessManager. + + void *status (void *status); + // Set the exit status (and return existing status). + + void *status (void); + // Get the current exit status. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Process_Manager *tm_; + // Pointer to the process manager for this block of code. + + void *status_; + // Keeps track of the exit status for the process. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Process_Manager.i" +#endif /* __ACE_INLINE__ */ +#endif + +#endif /* ACE_PROCESS_MANAGER_H */ + diff --git a/ace/Process_Manager.i b/ace/Process_Manager.i new file mode 100644 index 00000000000..1be8c04c67d --- /dev/null +++ b/ace/Process_Manager.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Process_Manager.i diff --git a/ace/Profile_Timer.cpp b/ace/Profile_Timer.cpp new file mode 100644 index 00000000000..406623c37df --- /dev/null +++ b/ace/Profile_Timer.cpp @@ -0,0 +1,226 @@ +// Profile_Timer.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Profile_Timer.h" + +#if defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) + +#if !defined (__ACE_INLINE__) +#include "ace/Profile_Timer.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Profile_Timer) + +void +ACE_Profile_Timer::dump (void) const +{ + ACE_TRACE ("ACE_Profile_Timer::dump"); +} + +// Initialize interval timer. + +ACE_Profile_Timer::ACE_Profile_Timer (void) +{ + ACE_TRACE ("ACE_Profile_Timer::ACE_Profile_Timer"); + ACE_OS::memset (&this->end_usage_, 0, sizeof this->end_usage_); + ACE_OS::memset (&this->begin_usage_, 0, sizeof this->begin_usage_); + ACE_OS::memset (&this->last_usage_, 0, sizeof this->last_usage_); + +#if defined (ACE_HAS_PRUSAGE_T) + ACE_OS::memset (&this->last_usage_, 0, sizeof this->last_usage_); + char buf[20]; + ACE_OS::sprintf (buf, "/proc/%d", ACE_OS::getpid ()); + + if ((this->proc_handle_ = ACE_OS::open (buf, O_RDONLY, 0)) == -1) + ACE_OS::perror (buf); +#elif defined (ACE_HAS_GETRUSAGE) + ACE_OS::memset (&this->begin_time_, 0, sizeof this->begin_time_); + ACE_OS::memset (&this->end_time_, 0, sizeof this->end_time_); + ACE_OS::memset (&this->last_time_, 0, sizeof this->last_time_); +#endif /* ACE_HAS_PRUSAGE_T */ +} + +// Terminate the interval timer. +ACE_Profile_Timer::~ACE_Profile_Timer (void) +{ + ACE_TRACE ("ACE_Profile_Timer::~ACE_Profile_Timer"); +#if defined (ACE_HAS_PRUSAGE_T) + if (ACE_OS::close (this->proc_handle_) == -1) + ACE_OS::perror ("ACE_Profile_Timer::~ACE_Profile_Timer"); +#endif /* ACE_HAS_PRUSAGE_T */ +} + +// Return the resource utilization. + +void +ACE_Profile_Timer::get_rusage (ACE_Profile_Timer::Rusage &usage) +{ + ACE_TRACE ("ACE_Profile_Timer::get_rusage"); + usage = this->end_usage_; +} + +#if defined (ACE_HAS_PRUSAGE_T) + +// Compute the amount of resource utilization since the start time. + +void +ACE_Profile_Timer::elapsed_rusage (ACE_Profile_Timer::Rusage &rusage) +{ + ACE_TRACE ("ACE_Profile_Timer::elapsed_rusage"); + rusage.pr_lwpid = this->end_usage_.pr_lwpid - this->last_usage_.pr_lwpid; + rusage.pr_count = this->end_usage_.pr_count - this->last_usage_.pr_count; + rusage.pr_minf = this->end_usage_.pr_minf - this->last_usage_.pr_minf; + rusage.pr_majf = this->end_usage_.pr_majf - this->last_usage_.pr_majf; + rusage.pr_inblk = this->end_usage_.pr_inblk - this->last_usage_.pr_inblk; + rusage.pr_oublk = this->end_usage_.pr_oublk - this->last_usage_.pr_oublk; + rusage.pr_msnd = this->end_usage_.pr_msnd - this->last_usage_.pr_msnd; + rusage.pr_mrcv = this->end_usage_.pr_mrcv - this->last_usage_.pr_mrcv; + rusage.pr_sigs = this->end_usage_.pr_sigs - this->last_usage_.pr_sigs; + this->subtract (rusage.pr_wtime, this->end_usage_.pr_wtime, this->last_usage_.pr_wtime); + this->subtract (rusage.pr_ltime, this->end_usage_.pr_ltime, this->last_usage_.pr_ltime); + this->subtract (rusage.pr_slptime, this->end_usage_.pr_slptime, this->last_usage_.pr_slptime); + rusage.pr_vctx = this->end_usage_.pr_vctx - this->last_usage_.pr_vctx; + rusage.pr_ictx = this->end_usage_.pr_ictx - this->last_usage_.pr_ictx; + rusage.pr_sysc = this->end_usage_.pr_sysc - this->last_usage_.pr_sysc; + rusage.pr_ioch = this->end_usage_.pr_ioch - this->last_usage_.pr_ioch; +} + +// Compute the elapsed time. + +void +ACE_Profile_Timer::compute_times (ACE_Elapsed_Time &et) +{ + ACE_TRACE ("ACE_Profile_Timer::compute_times"); + timestruc_t td; + + ACE_Profile_Timer::Rusage &end = this->end_usage_; + ACE_Profile_Timer::Rusage &begin = this->begin_usage_; + + this->subtract (td, end.pr_tstamp, begin.pr_tstamp); + et.real_time = td.tv_sec + ((double) td.tv_nsec) / (1000 * 1000 * 1000); + this->subtract (td, end.pr_utime, begin.pr_utime); + et.user_time = td.tv_sec + ((double) td.tv_nsec) / (1000 * 1000 * 1000); + this->subtract (td, end.pr_stime, begin.pr_stime); + et.system_time = td.tv_sec + ((double) td.tv_nsec) / (1000 * 1000 * 1000); +} + +// Determine the difference between T1 and T2. + +void +ACE_Profile_Timer::subtract (timestruc_t &tdiff, timestruc_t &t1, timestruc_t &t0) +{ + ACE_TRACE ("ACE_Profile_Timer::subtract"); + tdiff.tv_sec = t1.tv_sec - t0.tv_sec; + tdiff.tv_nsec = t1.tv_nsec - t0.tv_nsec; + + // Normalize the time. + + while (tdiff.tv_nsec < 0) + { + tdiff.tv_sec--; + tdiff.tv_nsec += (1000 * 1000 * 1000); + } +} + +#elif defined (ACE_HAS_GETRUSAGE) +// Compute the amount of resource utilization since the start time. + +void +ACE_Profile_Timer::elapsed_rusage (ACE_Profile_Timer::Rusage &usage) +{ + ACE_TRACE ("ACE_Profile_Timer::elapsed_rusage"); +#if !defined (ACE_WIN32) + // integral shared memory size + usage.ru_ixrss = this->end_usage_.ru_ixrss - this->last_usage_.ru_ixrss; + // integral unshared data " + usage.ru_idrss = this->end_usage_.ru_idrss - this->last_usage_.ru_idrss; + // integral unshared stack " + usage.ru_isrss = this->end_usage_.ru_isrss - this->last_usage_.ru_isrss; + // page reclaims - total vmfaults + usage.ru_minflt = this->end_usage_.ru_minflt - this->last_usage_.ru_minflt; + // page faults + usage.ru_majflt = this->end_usage_.ru_majflt - this->last_usage_.ru_majflt; + // swaps + usage.ru_nswap = this->end_usage_.ru_nswap - this->last_usage_.ru_nswap; + // block input operations + usage.ru_inblock = this->end_usage_.ru_inblock - + this->last_usage_.ru_inblock; + // block output operations + usage.ru_oublock = this->end_usage_.ru_oublock - + this->last_usage_.ru_oublock; + // messages sent + usage.ru_msgsnd = this->end_usage_.ru_msgsnd - this->last_usage_.ru_msgsnd; + // messages received + usage.ru_msgrcv = this->end_usage_.ru_msgrcv - this->last_usage_.ru_msgrcv; + // signals received + usage.ru_nsignals = this->end_usage_.ru_nsignals - + this->last_usage_.ru_nsignals; + // voluntary context switches + usage.ru_nvcsw = this->end_usage_.ru_nvcsw - this->last_usage_.ru_nvcsw; + // involuntary context switches + usage.ru_nivcsw = this->end_usage_.ru_nivcsw - this->last_usage_.ru_nivcsw; +#endif /* ACE_WIN32 */ +} + +void +ACE_Profile_Timer::compute_times (ACE_Elapsed_Time &et) +{ + ACE_TRACE ("ACE_Profile_Timer::compute_times"); + +#if defined (ACE_WIN32) + ACE_Time_Value atv = this->end_time_ - this->begin_time_; + et.real_time = atv.sec () + ((double) atv.usec ()) / (1000 * 1000); + + atv = ACE_Time_Value (this->end_usage_.ru_utime) + - ACE_Time_Value (this->begin_usage_.ru_utime); + + et.user_time = atv.sec () + ((double) atv.usec ()) / (1000 * 1000); + + atv = ACE_Time_Value (this->end_usage_.ru_stime) + - ACE_Time_Value (this->begin_usage_.ru_stime); + et.system_time = atv.sec () + ((double) atv.usec ()) / (1000 * 1000); +#else + timeval td; + + this->subtract (td, this->end_time_, this->begin_time_); + et.real_time = td.tv_sec + ((double) td.tv_usec) / (1000 * 1000); + + this->subtract (td, this->end_usage_.ru_utime, this->begin_usage_.ru_utime); + et.user_time = td.tv_sec + ((double) td.tv_usec) / (1000 * 1000); + + this->subtract (td, this->end_usage_.ru_stime, this->begin_usage_.ru_stime); + et.system_time = td.tv_sec + ((double) td.tv_usec) / (1000 * 1000); +#endif /* ACE_WIN32 */ +} + +// Determine the difference between T1 and T2. + +void +ACE_Profile_Timer::subtract (timeval &tdiff, timeval &t1, timeval &t0) +{ + ACE_TRACE ("ACE_Profile_Timer::subtract"); + tdiff.tv_sec = t1.tv_sec - t0.tv_sec; + tdiff.tv_usec = t1.tv_usec - t0.tv_usec; + + // Normalize the time. + + while (tdiff.tv_usec < 0) + { + tdiff.tv_sec--; + tdiff.tv_usec += (1000 * 1000); + } +} + +#endif /* ACE_HAS_PRUSAGE_T */ + +// Compute the amount of time that has elapsed between start and stop. + +int +ACE_Profile_Timer::elapsed_time (ACE_Elapsed_Time &et) +{ + ACE_TRACE ("ACE_Profile_Timer::elapsed_time"); + this->compute_times (et); + return 0; +} +#endif /* defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) */ diff --git a/ace/Profile_Timer.h b/ace/Profile_Timer.h new file mode 100644 index 00000000000..4234aef14f6 --- /dev/null +++ b/ace/Profile_Timer.h @@ -0,0 +1,142 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Profile_Timer.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_PROFILE_TIMER_H) +#define ACE_PROFILE_TIMER_H + +#include "ace/ACE.h" +#include "ace/Time_Value.h" + +#if !(defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) + +class ACE_Export ACE_Profile_Timer +{ +public: + struct ACE_Elapsed_Time + { + double real_time; + double user_time; + double system_time; + }; + + ACE_Profile_Timer (void) {} + ~ACE_Profile_Timer (void) {} + int start (void) { errno = ENOTSUP; return -1; } + int stop (void) { errno = ENOTSUP; return -1; } + int elapsed_time (ACE_Elapsed_Time &et) { errno = ENOTSUP; return -1; } +}; +#else +class ACE_Export ACE_Profile_Timer + // = TITLE + // A C++ wrapper for UNIX interval timers. +{ +public: + struct ACE_Elapsed_Time + { + double real_time; + double user_time; + double system_time; + }; + +#if defined (ACE_HAS_PRUSAGE_T) + typedef prusage_t Rusage; +#elif defined (ACE_HAS_GETRUSAGE) + typedef rusage Rusage; +#endif /* ACE_HAS_PRUSAGE_T */ + + // = Initialization and termination methods. + ACE_Profile_Timer (void); + // Default constructor. + + ~ACE_Profile_Timer (void); + // Shutdown the timer. + + // = Timer methods. + int start (void); + // Activate the timer. + + int stop (void); + // Stop the timer. + + // = Resource utilization methods. + int elapsed_time (ACE_Elapsed_Time &et); + // Compute the time elapsed since <start>. + + void elapsed_rusage (ACE_Profile_Timer::Rusage &rusage); + // Compute the amount of resource utilization since the start time. + + void get_rusage (ACE_Profile_Timer::Rusage &rusage); + // Return the resource utilization (don't recompute it). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + void compute_times (ACE_Elapsed_Time &et); + // Compute how much time has elapsed. + + ACE_Profile_Timer::Rusage begin_usage_; + // Keep track of the starting resource utilization. + + ACE_Profile_Timer::Rusage end_usage_; + // Keep track of the ending resource utilization. + + ACE_Profile_Timer::Rusage last_usage_; + // Keep track of the last rusage for incremental timing. + +#if defined (ACE_HAS_PRUSAGE_T) + void subtract (timestruc_t &tdiff, timestruc_t &t0, timestruc_t &t1); + // Substract two timestructs and store their difference. + + ACE_HANDLE proc_handle_; + // I/O handle for /proc file system. + +#elif defined (ACE_HAS_GETRUSAGE) + void subtract (timeval &tdiff, timeval &t0, timeval &t1); + // Substract two timestructs and store their difference. + + timeval begin_time_; + // Keep track of the beginning time. + + timeval end_time_; + // Keep track of the ending time. + + timeval last_time_; + // Keep track of the last time for incremental timing. +#elif defined (ACE_WIN32) + ACE_Time_Value begin_time_; + // Keep track of the beginning time. + + ACE_Time_Value end_time_; + // Keep track of the ending time. + + ACE_Time_Value last_time_; + // Keep track of the last time for incremental timing. + +#endif /* ACE_HAS_PRUSAGE_T */ +}; + +#if defined (__ACE_INLINE__) +#include "ace/Profile_Timer.i" +#endif /* __ACE_INLINE__ */ + +#endif /* defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) */ +#endif /* ACE_PROFILE_TIMER_H */ + diff --git a/ace/Profile_Timer.i b/ace/Profile_Timer.i new file mode 100644 index 00000000000..8ff9feec5a8 --- /dev/null +++ b/ace/Profile_Timer.i @@ -0,0 +1,48 @@ +/* -*- C++ -*- */ +// $Id$ + +// Profile_Timer.i + +#if defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) + +#if defined (ACE_HAS_PRUSAGE_T) +ACE_INLINE int +ACE_Profile_Timer::start (void) +{ + ACE_TRACE ("ACE_Profile_Timer::start"); + return ACE_OS::ioctl (this->proc_handle_, + PIOCUSAGE, + &this->begin_usage_); +} + +ACE_INLINE int +ACE_Profile_Timer::stop (void) +{ + ACE_TRACE ("ACE_Profile_Timer::stop"); + this->last_usage_ = this->end_usage_; + return ACE_OS::ioctl (this->proc_handle_, + PIOCUSAGE, + &this->end_usage_); +} +#elif defined (ACE_HAS_GETRUSAGE) +ACE_INLINE int +ACE_Profile_Timer::start (void) +{ + ACE_TRACE ("ACE_Profile_Timer::start"); + this->begin_time_ = ACE_OS::gettimeofday (); + ACE_OS::getrusage (RUSAGE_SELF, &this->begin_usage_); + return 0; +} + +ACE_INLINE int +ACE_Profile_Timer::stop (void) +{ + ACE_TRACE ("ACE_Profile_Timer::stop"); + this->last_time_ = this->end_time_; + this->end_time_ = ACE_OS::gettimeofday (); + this->last_usage_ = this->end_usage_; + ACE_OS::getrusage (RUSAGE_SELF, &this->end_usage_); + return 0; +} +#endif /* ACE_HAS_PRUSAGE_T */ +#endif /* defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE) */ diff --git a/ace/README b/ace/README new file mode 100644 index 00000000000..e39bd7a633c --- /dev/null +++ b/ace/README @@ -0,0 +1,784 @@ +ACE DEFINES +----------------------------------------------------------------------------- + +The following describes the meaning of the C++ compiler macros that +may be set in the DEFFLAGS Makefile macro. When you port ACE to a new +platform and/or C++ compiler, make sure that you check to see which of +these need to be defined. Eventually, most of this information should +be auto-discovered via GNU autoconf or Larry Wall's metaconfig... + +Macro Description +----- ----------- + +ACE_HAS_64BIT_LONGS Platform has 64bit longs and 32bit ints... +ACE_HAS_ALLOCA Compiler/platform supports alloca() +ACE_HAS_ALLOCA_H Compiler/platform has <alloca.h> +ACE_HAS_AUTOMATIC_INIT_FINI Compiler/platform correctly calls init()/fini() for shared libraries +ACE_HAS_BROKEN_BITSHIFT Compiler has integer overflow problem with bit-shift operations. +ACE_HAS_BROKEN_CTIME Compiler/platform uses macro for ctime (e.g., MVS) +ACE_HAS_BROKEN_MSG_H Platform headers don't support <msg.h> prototypes +ACE_HAS_BROKEN_MMAP_H HP/UX does not wrap the mmap(2) header files with extern "C". +ACE_HAS_BROKEN_POSIX_TIME Platform defines struct timespec in <sys/timers.h> +ACE_HAS_BROKEN_RANDR OS/compiler's header files are inconsistent with libC definition of rand_r(). +ACE_HAS_BROKEN_SENDMSG OS/compiler omits the const from the sendmsg() prototype. +ACE_HAS_BROKEN_SETRLIMIT OS/compiler omits the const from the rlimit parameter in the setrlimit() prototype. +ACE_HAS_BROKEN_WRITEV OS/compiler omits the const from the iovec parameter in the writev() prototype. +ACE_HAS_BSTRING Platform has <bstring.h> (which contains bzero() prototype) +ACE_HAS_CHARPTR_DL OS/platform uses char * for dlopen/dlsym args, rather than const char *. +ACE_HAS_CHARPTR_SOCKOPT OS/platform uses char * for sockopt, rather than const char * +ACE_HAS_COMPLEX_LOCK Platform supports non-standard readers/writer locks... +ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES Prototypes for both signal() and struct sigaction are consistent. +ACE_HAS_CPLUSPLUS_HEADERS Compiler/platform has correctly prototyped header files +ACE_HAS_DLL Build ACE using the frigging PC DLL nonsense... +ACE_HAS_GETRUSAGE Platform supports the getrusage() system call. +ACE_HAS_GNU_CSTRING_H Denotes that GNU has cstring.h as standard which redefines memchr() +ACE_HAS_GREENHILLS_SOCKETS Platform is using GreenHills compiler with its weird socket headers. +ACE_HAS_HI_RES_TIMER Compiler/platform supports SunOS high resolution timers +ACE_HAS_INLINED_OSCALLS Inline all the static class OS methods to remove call overhead +ACE_HAS_IP_MULTICAST Platform supports IP multicast +ACE_HAS_IRIX_GETTIMEOFDAY Denotes that IRIX 5.3 has second argument to gettimeofday() which is variable ... +ACE_HAS_IRIX62_THREADS Platform supports the very odd IRIX 6.2 threads... +ACE_HAS_LIMITED_RUSAGE_T The rusage_t structure has only two fields. +ACE_HAS_LONGLONG_T Compiler/platform supports the "long long" datatype. +ACE_HAS_LONG_MAP_FAILED Platform defines MAP_FAILED as a long constant. +ACE_HAS_MFC Platform supports Microsoft Foundation Classes +ACE_HAS_MSG Platform supports recvmsg and sendmsg +ACE_HAS_MT_SAFE_SOCKETS Sockets may be called in multi-threaded programs +ACE_HAS_NONCONST_GETBY Platform uses non-const char * in calls to gethostbyaddr, gethostbyname, getservbyname +ACE_HAS_OLD_MALLOC Compiler/platform uses old malloc()/free() prototypes (ugh) +ACE_HAS_ONEARG_SIGWAIT sigwait() takes only one argument. +ACE_HAS_ORBIX Platform has Orbix CORBA implementation +ACE_HAS_OSF_TIMOD_H Platform supports the OSF TLI timod STREAMS module +ACE_HAS_POLL Platform contains <poll.h> +ACE_HAS_POSIX_NONBLOCK Platform supports POSIX O_NONBLOCK semantics +ACE_HAS_POSIX_SEM Platform supports POSIX real-time semaphores (e.g., VxWorks and Solaris) +ACE_HAS_POSIX_TIME Platform supports the POSIX timespec_t type +ACE_HAS_PROC_FS Platform supports the /proc file system and defines tid_t in <sys/procfs.h> +ACE_HAS_PRUSAGE_T Platform supports the prusage_t struct +ACE_HAS_PTHREADS Platform supports POSIX Pthreads +ACE_HAS_PTHREAD_ATTR_INIT Platform requires pthread_*attr_init() rather than pthread_*attr_create() +ACE_HAS_PTHREAD_ATTR_DESTROY Platform requires pthread_*attr_destroy() rather than pthread_*attr_delete() +ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP Platform has pthread_condattr_setkind_np(). +ACE_HAS_PTHREAD_DSTATE_PTR pthread_attr_setdetachstate() takes pointer to 2nd arg. +ACE_HAS_PTHREAD_EQUAL Platform has pthread_equal(). +ACE_HAS_PTHREAD_GETSPECIFIC_DATAPTR pthread_getspecific() takes a data pointer for 2nd arg. +ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP Platform has pthread_mutexattr_setkind_np(). +ACE_HAS_PTHREAD_T Platform has pthread_t defined. +ACE_HAS_PTHREAD_YIELD_VOIDPTR pthread_yield() takes a void pointer arg. +ACE_HAS_REENTRANT_FUNCTIONS Platform supports reentrant functions (i.e., all the POSIX *_r functions). +ACE_HAS_REGEX Platform supports the POSIX regular expression library +ACE_HAS_RTLD_LAZY_V Explicit dynamic linking permits "lazy" symbol resolution +ACE_HAS_SELECT_H Platform has special header for select(). +ACE_HAS_SEMUN Compiler/platform defines a union semun for SysV shared memory +ACE_HAS_SIGINFO_T Platform supports SVR4 extended signals +ACE_HAS_SIGWAIT Platform/compiler has the sigwait(2) prototype +ACE_HAS_SIG_ATOMIC_T Compiler/platform defines the sig_atomic_t typedef +ACE_HAS_SIN_LEN Platform supports new BSD inet_addr len field. +ACE_HAS_SIZET_SOCKET_LEN OS/compiler uses size_t * rather than int * for socket lengths +ACE_HAS_SOCKIO_H Compiler/platform provides the sockio.h file +ACE_HAS_SPARCWORKS_401_SIGNALS Compiler has brain-damaged SPARCwork SunOS 4.x signal prototype... +ACE_HAS_SSIZE_T Compiler supports the ssize_t typedef +ACE_HAS_STHREADS Platform supports Solaris threads +ACE_HAS_STRBUF_T Compiler/platform supports struct strbuf +ACE_HAS_STREAMS Platform supports STREAMS +ACE_HAS_STREAM_PIPES Platform supports STREAM pipes +ACE_HAS_STRERROR Compiler/platform supports strerror () +ACE_HAS_STRUCT_NETDB_DATA Compiler/platform has strange hostent API for socket *_r() calls +ACE_HAS_STRUCT_PROTOENT_DATA Compiler/platform has strange protoent API for socket *_r() calls +ACE_HAS_SUNOS4_GETTIMEOFDAY SunOS 4 style prototype. +ACE_HAS_SUNOS4_SIGNAL_T Compiler has horrible SunOS 4.x signal handlers... +ACE_HAS_SVR4_DYNAMIC_LINKING Compiler/platform supports SVR4 dynamic linking semantics +ACE_HAS_SVR4_GETTIMEOFDAY Compiler/platform supports SVR4 gettimeofday() prototype +ACE_HAS_SVR4_SIGNAL_T Compiler/platform supports SVR4 signal typedef +ACE_HAS_SVR4_TIME Platform supports the SVR4 timestruc_t type +ACE_HAS_SVR4_TLI Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)... +ACE_HAS_SYSCALL_GETRUSAGE HP/UX has an undefined syscall for GETRUSAGE... +ACE_HAS_SYSCALL_H Compiler/platform contains the <sys/syscall.h> file. +ACE_HAS_SYSENT_H Platform provides <sysent.h> header +ACE_HAS_SYSINFO Platform supports system configuration information +ACE_HAS_SYSV_IPC Platform supports System V IPC (most versions of UNIX, but not Win32) +ACE_HAS_SYS_ERRLIST Platform/compiler supports _sys_errlist symbol +ACE_HAS_SYS_FILIO_H Platform provides <sys/filio.h> header +ACE_HAS_SYS_SIGLIST Compiler/platform supports sys_siglist array +ACE_HAS_TEMPLATE_TYPEDEFS Compiler implements templates that support typedefs inside of classes used as formal arguments to a template class. +ACE_HAS_TERM_IOCTLS Platform has terminal ioctl flags like TCGETS and TCSETS. +ACE_HAS_THREADS Platform supports threads +ACE_HAS_THREAD_SPECIFIC_STORAGE Compiler/platform has thread-specific storage +ACE_HAS_TID_T Platform supports the tid_t type (e.g., AIX) +ACE_HAS_TIMEZONE_GETTIMEOFDAY Platform/compiler supports timezone * as second parameter to gettimeofday() +ACE_HAS_TIMOD_H Platform supports TLI timod STREAMS module +ACE_HAS_TIUSER_H Platform supports TLI tiuser header +ACE_HAS_TLI Platform supports TLI +ACE_HAS_TLI_PROTOTYPES Platform provides TLI function prototypes +ACE_HAS_UCONTEXT_T Platform supports ucontext_t (which is used in the extended signal API). +ACE_HAS_UNION_WAIT The wait() system call takes a (union wait *) rather than int * +ACE_HAS_UNIXWARE_SVR4_SIGNAL_T Has inconsistent SVR4 signal stuff, but not the same as the other platforms +ACE_HAS_UNICODE Platform/compiler supports UNICODE +ACE_HAS_VOIDPTR_MMAP Platform requires void * for mmap(). +ACE_HAS_VOIDPTR_SOCKOPT OS/compiler uses void * arg 4 setsockopt() rather than const char * +ACE_HAS_WIN32_TRYLOCK The Win32 platform support TryEnterCriticalSection() +ACE_HAS_XLI Platform has the XLI version of TLI +ACE_HAS_XT Platform has Xt and Motif +ACE_HAS_YIELD_VOID_PTR Platform requires pthread_yield() to take a NULL. +ACE_LACKS_CONDATTR_PSHARED Platform has no implementation of pthread_condattr_setpshared(), even though it supports pthreads! +ACE_LACKS_MADVISE Platform lacks madvise() (e.g., Linux) +ACE_LACKS_MALLOC_H Platform lacks malloc.h +ACE_LACKS_MKTEMP ACE has no mktemp() +ACE_LACKS_MMAP The platform doesn't have mmap(2) (e.g., SCO UNIX). +ACE_LACKS_MODE_MASKS Platform/compiler doesn't have open() mode masks. +ACE_LACKS_MSGBUF_T Platform lacks struct msgbuf (e.g., NT and MSV). +ACE_LACKS_MSYNC Platform lacks msync() (e.g., Linux) +ACE_LACKS_PARAM_H Platform lacks <sys/param.h> (e.g., MVS) +ACE_LACKS_POSIX_PROTO Platform lacks POSIX prototypes for certain System V functions like shared memory and message queues. +ACE_LACKS_RECVMSG Platform lacks recvmsg() (e.g., Linux) +ACE_LACKS_RPC_H Platform lacks the ONC RPC header files. +ACE_LACKS_SBRK Platform lacks a working sbrk() (e.g., Win32 and VxWorks) +ACE_LACKS_SEMBUF_T Platform lacks struct sembuf (e.g., Win32 and VxWorks) +ACE_LACKS_SETDETACH Platform lacks pthread_attr_setdetachstate() (e.g., HP/UX 10.x) +ACE_LACKS_KEYDELETE Platform lacks TSS keydelete (e.g., HP/UX) +ACE_LACKS_SENDMSG Platform lacks sendmsg() (e.g., Linux) +ACE_LACKS_SI_ADDR Platform lacks the si_addr field of siginfo_t (e.g., VxWorks and HP/UX 10.x) +ACE_LACKS_SYSV_SHMEM Platform lacks System V shared memory (e.g., Win32 and VxWorks) +ACE_LACKS_SIGINFO_H Platform lacks the siginfo.h include file (e.g., MVS) +ACE_LACKS_SOCKETPAIR Platform lacks the socketpair() call (e.g., SCO UNIX) +ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES Compiler doesn't support static data member templates +ACE_LACKS_STRRECVFD Platform doesn't define struct strrecvfd. +ACE_LACKS_SYSCALL Platform doesn't have syscall() prototype +ACE_LACKS_SYSV_MSQ_PROTOS Platform doesn't have prototypes for Sys V msg()* queues. +ACE_LACKS_T_ERRNO Header files lack t_errno for TLI +ACE_LACKS_UCONTEXT_H Platform lacks the ucontext.h file +ACE_LACKS_UNIX_DOMAIN_SOCKETS ACE platform has no UNIX domain sockets +ACE_LACKS_UTSNAME_T Platform lacks struct utsname (e.g., Win32 and VxWorks) +ACE_MT_SAFE Compile using multi-thread libraries +ACE_NDEBUG Turns off debugging features +ACE_NEEDS_READV Platform doesn't define readv, so use our own +ACE_NEEDS_SYSTIME_H <time.h> doesn't automatically #include <sys/time.h> +ACE_NEEDS_WRITEV Platform doesn't define writev, so use our own +ACE_NLOGGING Turns off the LM_DEBUG and LM_ERROR logging macros... +ACE_NTRACE Turns off the tracing feature. +ACE_PAGE_SIZE Defines the page size of the system +ACE_REDEFINES_XTI_FUNCTIONS Platform redefines the t_... names (UnixWare) +ACE_SELECT_USES_INT Platform uses int for select() rather than fd_set +ACE_TEMPLATES_REQUIRE_PRAGMA Compiler's template mechanism must use a pragma This is used for AIX's C++ compiler. +ACE_TEMPLATES_REQUIRE_SOURCE Compiler's template mechanim must see source code (i.e., .cpp files). This is used for GNU G++. +ACE_TEMPLATES_REQUIRE_SPECIALIZATION Compiler's template mechanism requires the use of explicit C++ specializations for all used templates. This is also used for GNU G++ if you don't use the "repo" patches. +ACE_USE_POLL Use the poll() event demultiplexor rather than select(). +ACE_WSOCK_VERSION A parameter list indicating the version of WinSock (e.g., "1, 1" is version 1.1). +---------------------------------------- + +The following is a partial list of where some of these macros are used +in the code. This list was originally compiled by Jam Hamidi +(jh1@core01.osi.com). It is now hopelessly out of date. I hope +someone will come along and update it. + +ACE_HAS_ALLOCA: +--------------- + + Used in: + libsrc/IPC_SAP/SOCK_SAP/SOCK_Connect.C + for allocation of iovp + libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Msg.C + for alocation of iovp + + In solaris: + alloca() allocates size bytes of space in the stack frame of + the caller, and returns a pointer to the allocated block. + This temporary space is automatically freed when the caller + returns. Note: if the allocated block is beyond the current + stack limit, the resulting behavior is undefined. + + In HPUX: + no equivalent. + + Notes: + in HPUX it has to do new and delete. Affects performance. + + +ACE_HAS_AUTOMATIC_INIT_FINI: +---------------------------- + + Used in: + libsrc/Service_Configurator/Service_Repository.i + libsrc/Service_Configurator/Parse_Node.i + include/Parse_Node.i + include/Service_Repository.i + + In solaris: + _init() initializes a loadable module. It is called before + any other routine in a loadable module. + _info() returns information about a loadable module. + _fini() should return the return value from mod_remove(9F). + This flag if set, doesn't do anything. If not set, forces + _init() and _fini() to be executed as is: + dlsym ((char *) handle, "_fini"). + + In HPUX: + don't set. + Maybe have to look into shl_load( ), shl_definesym( ), + shl_findsym( ), shl_gethandle( ), shl_getsymbols( ), + shl_unload( ), shl_get( )(3X) - explicit load of shared libraries + Means Service Configurator won't be available. + TBA. + + +ACE_HAS_CPLUSPLUS_HEADERS: +-------------------------- + + Used In: + ace/OS.h + + HPUX: + set it. + + Notes: + If this is not defined, libc.h and osfcn.h get included. + Only needed for older compiler/OS platforms that don't + provide standard C++ header files in /usr/include. + +ACE_HAS_HI_RES_TIMER: +--------------------- + + Used In: + libsrc/Misc/High_Res_Timer.h + libsrc/Misc/High_Res_Timer.C + include/High_Res_Timer.h + + In Solaris, + C++ wrapper around gethrtime(), which returns a long long. + gethrtime() returns the current high-resolution real time. + Time is expressed as nanoseconds since some arbitrary time + in the past; it is not correlated in any way to the time of + day, and thus is not subject to resetting, drifting, etc. + + In HPUX + look into: getclock(), reltimer(), getitimer() + maybe even vtimes structure vm_utime, vm_stime ? + + Notes: + TBA + + +ACE_HAS_LONGLONG_T: +------------------- + + Used In: + libsrc/Misc/High_Res_Timer.i + libsrc/Misc/High_Res_Timer.C + include/High_Res_Timer.i + + Solaris: + has long long + + HPUX: + doesn't. + + +ACE_LACKS_T_ERRNO: +------------------- + + Used In: + ace/OS.h + + HPUX: + set it. + + Notes: + if set, adds: + extern int t_errno; + + +ACE_HAS_POSIX_NONBLOCK: +----------------------- + + Used in: + ace/OS.h + + HPUX: + set it. + + Notes: + if defined, sets ACE_NONBLOCK and O_NONBLOCK + O_NONBLOCK is used in libsrc/Misc/misc.C to do a + fcntl (fd, F_SETFL, opt) + ACE_NONBLOCK is used in libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv.C in the + disable member function and options passed to the open function + in libsrc/IPC_SAP/FIFO_SAP/FIFO.C + + +ACE_HAS_PROC_FS: +---------------- + + Used in: + ace/OS.h + libsrc/Misc/Profile_Timer.i + + Notes: + if set, includes <sys/procfs.h> + the PIOCUSAGE define is used in Profile_Timer. + + Solaris: + procfs.h defines things for the prpsinfo structure (basically to + do a "ps" from inside a program). + + HPUX: + don't set: obviously a different mechanism. + Look into /usr/include/sys/proc.h. The structure is proc. The + pointer to the kernel's proc table may be obtained by + extern struct proc *proc, *procNPROC; + extern int nproc; + + +ACE_HAS_PRUSAGE_T: +------------------ + + Used in: + libsrc/Misc/Profile_Timer.h + libsrc/Misc/Profile_Timer.C + + Notes: + If defined, declares the Profile_Timer class that does start(), + stop() and basically gets real_time, user_time, system_time for + an interval. + This stuff is highly non-portable. + + HPUX: + don't set + + +ACE_HAS_RTLD_LAZY_V: +-------------------- + + Used in: + ace/OS.h + + Notes: + if not defined, does a: + #defines RTLD_LAZY 1. + This is the mode argument passed to dlopen(path,mode), used in + libsrc/Service_Configurator/Parse_Node.i + + Solaris: + dlopen() is one of a family of routines that give the user + direct access to the dynamic linking facilities. (SEE + SunOS 5.3 Linker and Libraries Manual ). These routines are + made available via the library loaded when the option -ldl + is passed to the link-editor. + + These routines are available to dynamically linked execut- + ables ONLY. + + HPUX: + don't set. + look into: + shl_load( ), shl_definesym( ), shl_findsym( ), shl_gethandle( ), + shl_getsymbols( ), shl_unload( ), shl_get( )(3X) + - explicit load of shared libraries + + +ACE_HAS_SEMUN: +-------------- + + Used in: + libsrc/Semaphores/Semaphore_Simple.h + + Notes: + if not defined, defines semun as: + union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + ushort *array; /* array for GETALL & SETALL */ + }; + + HPUX: + don't set. + in /usr/include/sem.h: + /* The fourth argument to semctl() varies depending on the value of + its first argument. If desired, "union semun" can be declared + by the user, but this is not necessary since the individual + member can just be passed as the argument. */ + + +ACE_HAS_SIG_ATOMIC_T: +--------------------- + + Used in: + ace/OS.h + + Notes: + if not defined, does a: + typedef int sig_atomic_t; + This is used in the Reactor and service configurator. + + HPUX: + set it. + in /usr/include/sys/signal.h: + typedef unsigned int sig_atomic_t; + + +ACE_HAS_SSIZE_T: +---------------- + + Used in: + ace/OS.h + + Notes: + if not defined, does a + typedef int ssize_t; + used mostly in IPC_SAP. (don't confuse with size_t). + + HPUX: + set it. + in /usr/include/sys/types.h + + +ACE_HAS_STRBUF_T: +----------------- + + Used in: + include/Str_Buf.h + + Notes: + if not defined, declares the strbuf structure as: + struct strbuf + { + int maxlen; /* no. of bytes in buffer */ + int len; /* no. of bytes returned */ + void *buf; /* pointer to data */ + }; + + Solaris: + defined in /usr/include/sys/stropts.h + Sys V.4 Streams. + uses strbuf as parameter to putmsg, putpmsg: + int putmsg(int fildes, const struct strbuf *ctlptr, + const struct strbuf *dataptr, int flags); + + HPUX: + don't set. + no SYS V.4 streams. + + +ACE_HAS_STREAMS: +---------------- + + Used In: + ace/OS.h + libsrc/IPC_SAP/SOCK_SAP/LSOCK.C + + Notes: + if defined, includes <stropts.h> + + HPUX: + don't set. + no SYS V.4 streams. + + +ACE_HAS_STREAM_PIPES: +--------------------- + + Used in: + libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Msg.h + libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Msg.C + libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Listener.h + libsrc/IPC_SAP/SPIPE_SAP/SPIPE_Listener.C + libsrc/IPC_SAP/SPIPE_SAP/SPIPE.h + libsrc/IPC_SAP/SPIPE_SAP/SPIPE.C + libsrc/IPC_SAP/FIFO_SAP/FIFO_Send_Msg.h + libsrc/IPC_SAP/FIFO_SAP/FIFO_Send_Msg.C + libsrc/IPC_SAP/FIFO_SAP/FIFO_Send_Msg.i + libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv_Msg.h + libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv_Msg.C + libsrc/IPC_SAP/FIFO_SAP/FIFO_Recv_Msg.i + + Notes: + if not set, won't be able to use the SPIPE class (IPC_SAP) with + rendezvous handles. + + HPUX: + don't set. + No sysV.4 streams. + + +ACE_HAS_STRERROR: +----------------- + + Used in: + ace/OS.h + + Notes: + if not defined, does a: + #define strerror(err) sys_errlist[err] + + Solaris: + /usr/include/string.h + + HPUX: + set it. + in /usr/include/sys/errno.h and string.h + extern char *strerror (int); + + +ACE_HAS_SVR4_DYNAMIC_LINKING: +----------------------------- + + Used in: + ace/OS.h + tests/Service_Configurator/CCM_App.C + + Notes: + if defined, includes <dlfcn.h> + with dlopen(), dlsym(), etc.. + + HPUX: + don't set. + has its own: + shl_findsym( ), shl_gethandle( ), shl_getsymbols( ), + shl_unload( ), shl_get( )(3X) - explicit load of shared libraries + + +ACE_HAS_SVR4_GETTIMEOFDAY: +-------------------------- + + Used in: + ace/OS.h + libsrc/Reactor/Timer_Queue.i + + Notes: + has to do with gettimeofday (). + + Solaris: + gettimeofday (struct timeval *tp) + + HPUX: + don't set. + it has gettimeofday (struct timeval *tp, struct timezone *tzp); + most calls do a: + #if defined (ACE_HAS_SVR4_GETTIMEOFDAY) + ::gettimeofday (&cur_time); + #else + ::gettimeofday (&cur_time, 0); + #endif /* ACE_HAS_SVR4_GETTIMEOFDAY */ + + +ACE_HAS_POLL: +------------ + Used in: + ace/OS.h + + Notes: + #if defined (ACE_HAS_POLL) + #include <poll.h> + #endif /* ACE_HAS_POLL */ + +ACE_USE_POLL_IMPLEMENTATION: +------------------ + + Used in: + ace/OS.h + + Notes: + Use the poll() event demultiplexor rather than select(). + + HPUX: + set it. + + +ACE_HAS_SVR4_SIGNAL_T: +---------------------- + + Used in: + ace/OS.h + + Notes: + #if defined (ACE_HAS_SVR4_SIGNAL_T) + typedef void (*SignalHandler)(int); + typedef void (*SignalHandlerV)(void); + #elif defined (ACE_HAS_SIGNALHANDLERV_INT_ARG) + typedef void (*SignalHandler)(int); + typedef void (*SignalHandlerV)(int); + #else + #define SignalHandler SIG_PF + typedef void (*SignalHandlerV)(...); + #endif /* ACE_HAS_SVR4_SIGNAL_T */ + + HPUX: + set it. + + +ACE_HAS_SVR4_TLI: +----------------- + + Used in: + libsrc/IPC_SAP/TLI_SAP/TLI.C + libsrc/IPC_SAP/TLI_SAP/TLI.h + libsrc/IPC_SAP/TLI_SAP/TLI_Stream.C + + Notes: + TLI is the transport layer calls as in: t_bind(), t_open(), t_unbind(), + t_optmgmt(), ... in SunOS and Solaris. + + HPUX: + don't set. + Not supported. + + +ACE_HAS_SYS_FILIO_H: +-------------------- + + Used in: + ace/OS.h + + Notes: + if not defined, includes <sys/filio.h>. + didn't find any reference to anything in this file in the ACE code. + + Solaris: + filio.h defines FIOCLEX, FIOASYNC, ... as _IO('f', 1), .. + for FIOLFS,.. solaris has this to say: + /* + * ioctl's for Online: DiskSuite. + * WARNING - the support for these ioctls may be withdrawn + * in the future OS releases. + */ + + HPUX: + <sys/ioctl.h> defines FIOASYNC and some other ones, + <sgtty.h> defines some like FIOCLEX. + some are never defined. + use #ifdef HP-UX to modify sysincludes.h + + +ACE_HAS_SYS_SIGLIST: +-------------------- + + Used in: + ace/OS.h + libsrc/Log_Msg/Log_Msg.C + + Notes: + if not defined, does a: + extern const char **_sys_siglist; + + Solaris: + This is an array holding signal descriptions. + + HPUX: + don't set. + Some additional work is required. In libsrc/Log_Msg/Log_Msg.C, + sys_siglist is used regardless of ACE_HAS_SYS_SIGLIST. + have to add #ifdefs to remove them. + + +ACE_HAS_TEMPLATE_TYPEDEFS: +-------------------------- + + Used in: + libsrc/ASX/*.[Chi] + + Notes: + cfront-based C++ compilers don't implement templates that support + classes with typedefs of other types as formal arguments. This + typedef uses the C++ preprocessor to work around this problem. + +ACE_HAS_THREADS: +---------------- + + Used in: + libsrc/Service_Configurator/Service_Record.i + libsrc/Service_Configurator/Svc_Conf.y.C + libsrc/Service_Configurator/Thread_Spawn.i + libsrc/Threads/Synch.C + libsrc/Threads/Synch.i + libsrc/Threads/Thr_Manager.i + libsrc/ASX/STREAM.C + libsrc/ASX/Queue.C + libsrc/ASX/Module.C + libsrc/ASX/Stream_Modules.C + libsrc/ASX/Multiplexor.C + libsrc/ASX/Message_List.C + include/Message_List.h + include/Module.h + include/Multiplexor.h + include/Queue.h + include/STREAM.h + include/Stream_Modules.h + include/Service_Record.h + include/Thread_Spawn.h + include/Synch.h + include/Thr_Manager.h + + Notes: + We use Message_List.h even in a non-threaded environment. + our XOMessageList.h does this by #ifdefs around Threaded things. + + HPUX: + not until 10.0. + + +ACE_HAS_THREAD_T: +----------------- + + Used in: + ace/OS.h + + Notes: + #if !defined (ACE_HAS_THREAD_T) + typedef int thread_t; + #endif /* !ACE_HAS_THREAD_T */ + + HPUX: + don't set. + + +ACE_HAS_TIMOD_H: +---------------- + + Used in: + ace/OS.h + + Notes: + if defined, include <sys/timod.h> + + Solaris: + timod is a STREAMS module for use with the Transport Inter- + face (TI) functions of the Network Services library. The + timod module converts a set of ioctl(2) calls into STREAMS + messages that may be consumed by a transport protocol pro- + vider that supports the Transport Interface. This allows a + user to initiate certain TI functions as atomic operations. + + HPUX: + don't set. + + +ACE_HAS_TIUSER_H: +----------------- + + Used in: + ace/OS.h + + Notes: + if set, includes <tiuser.h> + + Solaris: + in conjunction with t_bind, t_accept, etc.. transport layer. + + HPUX: + don't set. + + +ACE_USE_POLL_IMPLEMENTATION: +---------------------------- + + Used in: + libsrc/Reactor/Reactor.i + include/Event_Handler.h + ace/OS.h + include/Reactor.h + + Notes: + in the reactor, use poll instead of select. In general, + good thing to have set. + + Don't set this, it will get set by ACE_HAS_SVR4_POLL + diff --git a/ace/Reactor.cpp b/ace/Reactor.cpp new file mode 100644 index 00000000000..524e9cc434a --- /dev/null +++ b/ace/Reactor.cpp @@ -0,0 +1,1614 @@ +// Reactor.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Synch_T.h" +#include "ace/SOCK_Acceptor.h" +#include "ace/SOCK_Connector.h" +#include "ace/Reactor.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_Reactor) + +struct ACE_Notification_Buffer +{ + ACE_Notification_Buffer (void); + + ACE_Notification_Buffer (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + + ACE_Event_Handler *eh_; + // Pointer to the Event_Handler that will be dispatched + // by the main event loop. + + ACE_Reactor_Mask mask_; + // Mask that indicates which method to call. +}; + +ACE_Notification_Buffer::ACE_Notification_Buffer (void) {} + +ACE_Notification_Buffer::ACE_Notification_Buffer (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask) + : eh_ (eh), + mask_ (mask) +{ +} + +// Performs sanity checking on the ACE_HANDLE. + +int +ACE_Handler_Repository::invalid_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Handler_Repository::invalid_handle"); +#if defined (ACE_WIN32) + return handle == ACE_INVALID_HANDLE; +#else /* !ACE_WIN32 */ + return handle < 0 || handle >= this->max_size_; +#endif /* ACE_WIN32 */ +} + +size_t +ACE_Handler_Repository::max_handlep1 (void) +{ + ACE_TRACE ("ACE_Handler_Repository::max_handlep1"); + +#if defined (ACE_WIN32) + return this->cur_size_; +#else + return this->max_handlep1_; +#endif /* ACE_WIN32 */ +} + +int +ACE_Handler_Repository::open (size_t size) +{ + ACE_TRACE ("ACE_Handler_Repository::open"); + this->max_size_ = size; + +#if defined (ACE_WIN32) + this->cur_size_ = 0; + + // Try to allocate the memory. + ACE_NEW_RETURN (this->event_handlers_, ACE_NT_EH_Record[size], -1); + + // Initialize the ACE_Event_Handler * to ACE_INVALID_HANDLE; + for (size_t h = 0; h < size; h++) + { + this->event_handlers_[h].handle_ = ACE_INVALID_HANDLE; + this->event_handlers_[h].event_handler_ = 0; + } +#else + this->max_handlep1_ = 0; + + // Try to allocate the memory. + ACE_NEW_RETURN (this->event_handlers_, ACE_Event_Handler *[size], -1); + + // Initialize the ACE_Event_Handler * to NULL. + for (size_t h = 0; h < size; h++) + this->event_handlers_[h] = 0; + +#endif /* ACE_WIN32 */ + return 0; +} + +// Initialize a repository of the appropriate <size>. + +ACE_Handler_Repository::ACE_Handler_Repository (void) + : event_handlers_ (0), + max_size_ (0), +#if defined (ACE_WIN32) + cur_size_ (0) +#else + max_handlep1_ (ACE_INVALID_HANDLE) +#endif /* ACE_WIN32 */ +{ + ACE_TRACE ("ACE_Handler_Repository::ACE_Handler_Repository"); +} + +int +ACE_Handler_Repository::close (ACE_Reactor *reactor) +{ + ACE_TRACE ("ACE_Handler_Repository::close"); + + if (this->event_handlers_ != 0) + { +#if defined(ACE_WIN32) + for (ssize_t i = 0; + i < this->cur_size_; + i++) + reactor->detach (this->event_handlers_[i].handle_, + ACE_Event_Handler::RWE_MASK); + + delete [] this->event_handlers_; + this->event_handlers_ = 0; +#else + for (ACE_HANDLE h = 0; + h < this->max_handlep1_; + h++) + reactor->detach (h, ACE_Event_Handler::RWE_MASK); + + delete [] this->event_handlers_; + this->event_handlers_ = 0; +#endif /* !ACE_WIN32 */ + } + return 0; +} + +// Return the <ACE_Event_Handler *> associated with <ACE_HANDLE>. + +ACE_Event_Handler * +ACE_Handler_Repository::find (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Handler_Repository::find"); +#if defined (ACE_WIN32) + for (ssize_t i = 0; i < this->cur_size_; i++) + if (this->event_handlers_[i].handle_ == handle) + return this->event_handlers_[i].event_handler_; + + return 0; +#else + if (handle < 0 || handle >= this->max_handlep1_) + return 0; + else + return this->event_handlers_[handle]; +#endif /* ACE_WIN32 */ +} + +// Bind the <ACE_Event_Handler *> to the <ACE_HANDLE>. + +int +ACE_Handler_Repository::bind (ACE_HANDLE handle, + ACE_Event_Handler *event_handler) +{ + ACE_TRACE ("ACE_Handler_Repository::bind"); +#if defined (ACE_WIN32) + int first_free = -1; + + for (ssize_t i = 0; i < this->cur_size_; i++) + if (this->event_handlers_[i].handle_ == handle) + { + // If the HANDLE is already here just reassign the + // Event_Handler. + this->event_handlers_[i].event_handler_ = event_handler; + return 0; + } + else if (this->event_handlers_[i].handle_ == ACE_INVALID_HANDLE + && first_free == -1) + first_free = i; + + if (first_free > -1) + // We found a free spot, let's reuse it (and the comments ;-)). + { + this->event_handlers_[first_free].handle_ = handle; + this->event_handlers_[first_free].event_handler_ = event_handler; + return 0; + } + else if (this->cur_size_ < this->max_size_) + { + // Insert at the end of the active portion. + this->event_handlers_[this->cur_size_].handle_ = handle; + this->event_handlers_[this->cur_size_].event_handler_ = event_handler; + this->cur_size_++; + return 0; + } + else + { + // No more room! + errno = ENOMEM; + return -1; + } +#else + this->event_handlers_[handle] = event_handler; + + if (this->max_handlep1_ < handle + 1) + this->max_handlep1_ = handle + 1; + return 0; +#endif /* ACE_WIN32 */ +} + +// Remove the binding of <ACE_HANDLE>. + +int +ACE_Handler_Repository::unbind (ACE_HANDLE handle, + ACE_Handle_Set &rd_mask, + ACE_Handle_Set &wr_mask, + ACE_Handle_Set &ex_mask) +{ + ACE_TRACE ("ACE_Handler_Repository::unbind"); +#if defined (ACE_WIN32) + // If all the events were cleared then totally shut down Event + // Handler. + + if (rd_mask.is_set (handle) == 0 + && wr_mask.is_set (handle) == 0 + && ex_mask.is_set (handle) == 0) + { + for (ssize_t i = 0; i < this->cur_size_; i++) + if (this->event_handlers_[i].handle_ == handle) + { + this->event_handlers_[i].handle_ = ACE_INVALID_HANDLE; + this->event_handlers_[i].event_handler_ = 0; + + if (this->cur_size_ == i + 1) + { + // We've deleted the last entry (i.e., i + 1 == the + // current size of the array), so we need to figure + // out the last valid place in the array that is worth + // looking at. + + for (int i = this->cur_size_ - 1; + i >= 0 && this->event_handlers_[i].handle_ == ACE_INVALID_HANDLE; + i--) + continue; + + this->cur_size_ = i + 1; + } + break; + } + } + + return 0; +#else + // If all the events were cleared then totally shut down Event + // Handler. + + if (handle < 0 || handle >= this->max_handlep1_) + return -1; + + if (rd_mask.is_set (handle) == 0 + && wr_mask.is_set (handle) == 0 + && ex_mask.is_set (handle) == 0) + { + this->event_handlers_[handle] = 0; + + if (this->max_handlep1_ == handle + 1) + { + // We've deleted the last entry, so we need to figure out + // the last valid place in the array that is worth looking + // at. + ACE_HANDLE rd_max = rd_mask.max_set (); + ACE_HANDLE wr_max = wr_mask.max_set (); + ACE_HANDLE ex_max = ex_mask.max_set (); + + // Compute the maximum of three values. + this->max_handlep1_ = rd_max < wr_max ? wr_max : rd_max; + if (this->max_handlep1_ < ex_max) + this->max_handlep1_ = ex_max; + + this->max_handlep1_++; + } + } + return 0; +#endif /* ACE_WIN32 */ +} + +ACE_Handler_Repository_Iterator::ACE_Handler_Repository_Iterator (const ACE_Handler_Repository &s) + : rep_ (s), + current_ (-1) +{ + this->advance (); +} + +// Pass back the <next_item> that hasn't been seen in the Set. +// Returns 0 when all items have been seen, else 1. + +int +ACE_Handler_Repository_Iterator::next (ACE_Event_Handler *&next_item) +{ +#if defined (ACE_WIN32) + if (this->current_ >= this->rep_.cur_size_) + return 0; + else + { + next_item = this->rep_.event_handlers_[this->current_].event_handler_; + return 1; + } + +#else + if (this->current_ >= this->rep_.max_handlep1_) + return 0; + else + { + next_item = this->rep_.event_handlers_[this->current_]; + return 1; + } +#endif /* ACE_WIN32 */ +} + +// Move forward by one element in the set. + +int +ACE_Handler_Repository_Iterator::advance (void) +{ +#if defined (ACE_WIN32) + if (this->current_ < this->rep_.cur_size_) + this->current_++; + + while (this->current_ < this->rep_.cur_size_) + if (this->rep_.event_handlers_[this->current_].handle_ != ACE_INVALID_HANDLE) + return 1; + else + this->current_++; + + return 0; +#else + if (this->current_ < this->rep_.max_handlep1_) + this->current_++; + + while (this->current_ < this->rep_.max_handlep1_) + if (this->rep_.event_handlers_[this->current_] != 0) + return 1; + else + this->current_++; + + return 0; +#endif /* ACE_WIN32 */ +} + +// Dump the state of an object. + +void +ACE_Handler_Repository_Iterator::dump (void) const +{ + ACE_TRACE ("ACE_Handler_Repository_Iterator::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "current_ = %d", this->current_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Handler_Repository::dump (void) const +{ + ACE_TRACE ("ACE_Handler_Repository::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); +#if defined (ACE_WIN32) + ACE_DEBUG ((LM_DEBUG, + "(%t) cur_size_ = %d, max_size_ = %d\n", + this->cur_size_, this->max_size_)); +#else + ACE_DEBUG ((LM_DEBUG, + "(%t) max_handlep1_ = %d, max_size_ = %d\n", + this->max_handlep1_, this->max_size_)); +#endif /* ACE_WIN32 */ + + ACE_DEBUG ((LM_DEBUG, "[")); + + ACE_Event_Handler *eh = 0; + + for (ACE_Handler_Repository_Iterator iter (*this); + iter.next (eh) != 0; + iter.advance ()) + ACE_DEBUG ((LM_DEBUG, " (eh = %x, eh->handle_ = %d)", eh, eh->get_handle ())); + + ACE_DEBUG ((LM_DEBUG, " ]")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Handler_Repository_Iterator) + +void +ACE_Reactor::dump (void) const +{ + ACE_TRACE ("ACE_Reactor::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + this->timer_queue_->dump (); + this->handler_rep_.dump (); + this->signal_handler_->dump (); + ACE_DEBUG ((LM_DEBUG, "delete_signal_handler_ = %d\n", this->delete_signal_handler_)); + + ACE_HANDLE h; + + for (ACE_Handle_Set_Iterator handle_iter_wr (this->wr_handle_mask_); + (h = handle_iter_wr ()) != ACE_INVALID_HANDLE; + ++handle_iter_wr) + ACE_DEBUG ((LM_DEBUG, "write_handle = %d\n", h)); + + for (ACE_Handle_Set_Iterator handle_iter_rd (this->rd_handle_mask_); + (h = handle_iter_rd ()) != ACE_INVALID_HANDLE; + ++handle_iter_rd) + ACE_DEBUG ((LM_DEBUG, "read_handle = %d\n", h)); + + for (ACE_Handle_Set_Iterator handle_iter_ex (this->ex_handle_mask_); + (h = handle_iter_ex ()) != ACE_INVALID_HANDLE; + ++handle_iter_ex) + ACE_DEBUG ((LM_DEBUG, "except_handle = %d\n", h)); + + for (ACE_Handle_Set_Iterator handle_iter_wr_ready (this->wr_handle_mask_ready_); + (h = handle_iter_wr_ready ()) != ACE_INVALID_HANDLE; + ++handle_iter_wr_ready) + ACE_DEBUG ((LM_DEBUG, "write_handle_ready = %d\n", h)); + + for (ACE_Handle_Set_Iterator handle_iter_rd_ready (this->rd_handle_mask_ready_); + (h = handle_iter_rd_ready ()) != ACE_INVALID_HANDLE; + ++handle_iter_rd_ready) + ACE_DEBUG ((LM_DEBUG, "read_handle_ready = %d\n", h)); + + for (ACE_Handle_Set_Iterator handle_iter_ex_ready (this->ex_handle_mask_ready_); + (h = handle_iter_ex_ready ()) != ACE_INVALID_HANDLE; + ++handle_iter_ex_ready) + ACE_DEBUG ((LM_DEBUG, "except_handle_ready = %d\n", h)); + + ACE_DEBUG ((LM_DEBUG, "restart_ = %d\n", this->restart_)); + ACE_DEBUG ((LM_DEBUG, "\nrequeue_position_ = %d\n", this->requeue_position_)); + ACE_DEBUG ((LM_DEBUG, "\ninitialized_ = %d\n", this->initialized_)); + ACE_DEBUG ((LM_DEBUG, "\nowner_ = %d\n", this->owner_)); + +#if defined (ACE_MT_SAFE) + this->notification_handler_.dump (); + this->token_.dump (); +#endif /* ACE_MT_SAFE */ + + this->timer_skew_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_Reactor::handler_i (int signum, ACE_Event_Handler **eh) +{ + ACE_TRACE ("ACE_Reactor::handler_i"); + ACE_Event_Handler *handler = this->signal_handler_->handler (signum); + + if (handler == 0) + return -1; + else if (*eh != 0) + *eh = handler; + return 0; +} + +void +ACE_Reactor::owner (ACE_thread_t tid, ACE_thread_t *o_id) +{ + ACE_TRACE ("ACE_Reactor::owner"); + ACE_MT (ACE_GUARD (ACE_REACTOR_MUTEX, ace_mon, this->token_)); + + if (o_id) + *o_id = this->owner_; + + this->owner_ = tid; +} + +int +ACE_Reactor::owner (ACE_thread_t *t_id) +{ + ACE_TRACE ("ACE_Reactor::owner"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + *t_id = this->owner_; + return 0; +} + +void +ACE_Reactor::requeue_position (int rp) +{ + ACE_TRACE ("ACE_Reactor::requeue_position"); + ACE_MT (ACE_GUARD (ACE_REACTOR_MUTEX, ace_mon, this->token_)); + this->requeue_position_ = rp; +} + +int +ACE_Reactor::requeue_position (void) +{ + ACE_TRACE ("ACE_Reactor::requeue_position"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->requeue_position_; +} + +#if defined (ACE_MT_SAFE) +// Enqueue ourselves into the list of waiting threads. +void +ACE_Reactor::renew (void) +{ + ACE_TRACE ("ACE_Reactor::renew"); + this->token_.renew (this->requeue_position_); +} + +void +ACE_Reactor_Token::dump (void) const +{ + ACE_TRACE ("ACE_Reactor_Token::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Reactor_Token::ACE_Reactor_Token (ACE_Reactor &r) + : reactor_ (r) +#if defined (ACE_REACTOR_HAS_DEADLOCK_DETECTION) + , ACE_Local_Mutex (0) // Triggers unique name by stringifying "this"... +#endif /* ACE_REACTOR_HAS_DEADLOCK_DETECTION */ +{ + ACE_TRACE ("ACE_Reactor_Token::ACE_Reactor_Token"); +} + +// Used to wakeup the Reactor. + +void +ACE_Reactor_Token::sleep_hook (void) +{ + ACE_TRACE ("ACE_Reactor_Token::sleep_hook"); + if (this->reactor_.notify () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "sleep_hook failed")); +} + +void +ACE_Notification_Handler::dump (void) const +{ + ACE_TRACE ("ACE_Notification_Handler::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "reactor_ = %x", this->reactor_)); + this->notification_pipe_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +int +ACE_Notification_Handler::open (ACE_Reactor *r) +{ + ACE_TRACE ("ACE_Notification_Handler::open"); + + this->reactor_ = r; + this->notification_pipe_.open (); + +#if !defined (ACE_WIN32) // There seems to be a Win32 bug with this... + // Set this into non-blocking mode. + if (ACE::set_flags (this->notification_pipe_.read_handle (), + ACE_NONBLOCK) == -1) + return -1; + else +#endif /* !ACE_WIN32 */ + if (this->reactor_->register_handler (this->notification_pipe_.read_handle (), + this, + ACE_Event_Handler::READ_MASK) == -1) + return -1; + return 0; +} + +int +ACE_Notification_Handler::close (void) +{ + ACE_TRACE ("ACE_Notification_Handler::close"); + return this->notification_pipe_.close (); +} + +ssize_t +ACE_Notification_Handler::notify (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Notification_Handler::notify"); + ACE_Notification_Buffer buffer (eh, mask); + + ssize_t n = ACE::send (this->notification_pipe_.write_handle (), + (char *) &buffer, + sizeof buffer); + if (n == -1) + return -1; + return 0; +} + +// Handles pending threads (if any) that are waiting to unblock the +// Reactor. + +int +ACE_Notification_Handler::handle_notifications (ACE_Handle_Set &rmask) +{ + ACE_TRACE ("ACE_Notification_Handler::handle_notification"); + + ACE_HANDLE read_handle = this->notification_pipe_.read_handle (); + + if (rmask.is_set (read_handle)) + { + this->reactor_->notify_handle + (read_handle, ACE_Event_Handler::READ_MASK, + this->reactor_->rd_handle_mask_ready_, + this->reactor_->handler_rep_.find (read_handle), + &ACE_Event_Handler::handle_input); + return 1; + } + else + return 0; +} + +// Special trick to unblock select() or poll() when updates occur in +// somewhere other than the main ACE_Reactor thread. All we do is +// write data to a pipe that the ACE_Reactor is listening on. Thanks +// to Paul Stephenson at Ericsson for suggesting this approach. + +int +ACE_Notification_Handler::handle_input (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Notification_Handler::handle_input"); + // Precondition: this->reactor_.token_.current_owner () == + // ACE_Thread::self (); + + ACE_ASSERT (this->notification_pipe_.read_handle () == handle); + + ACE_Notification_Buffer buffer; + ssize_t n; + +#if defined (ACE_WIN32) + if ((n = ACE::recv (handle, (char *) &buffer, sizeof buffer)) == -1) + return -1; + // Put ourselves at the head of the queue. + this->reactor_->requeue_position (0); +#else + while ((n = ACE::recv (handle, (char *) &buffer, sizeof buffer)) != -1) +#endif /* ACE_WIN32 */ + { + // If eh == 0 then another thread is unblocking the ACE_Reactor + // to update the ACE_Reactor's internal structures. Otherwise, + // we need to dispatch the appropriate handle_* method on the + // ACE_Event_Handler pointer we've been passed. + if (buffer.eh_ != 0) + { + int result = 0; + + switch (buffer.mask_) + { + case ACE_Event_Handler::READ_MASK: + result = buffer.eh_->handle_input (ACE_INVALID_HANDLE); + break; + case ACE_Event_Handler::WRITE_MASK: + result = buffer.eh_->handle_output (ACE_INVALID_HANDLE); + break; + case ACE_Event_Handler::EXCEPT_MASK: + result = buffer.eh_->handle_exception (ACE_INVALID_HANDLE); + break; + default: + ACE_ERROR ((LM_ERROR, "invalid mask = %d\n", buffer.mask_)); + break; + } + if (result == -1) + buffer.eh_->handle_close (ACE_INVALID_HANDLE, + ACE_Event_Handler::EXCEPT_MASK); + } + } + + // Enqueue ourselves into the list of waiting threads. When we + // reacquire the token we'll be off and running again with ownership + // of the token. + this->reactor_->renew (); + + // Postcondition: this->reactor_.token_.current_owner () == + // ACE_Thread::self (); + return n == -1 && errno != EWOULDBLOCK ? -1 : 0; +} +#endif /* ACE_MT_SAFE */ + +int +ACE_Reactor::notify (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::notify"); + + ssize_t n = 0; +#if defined (ACE_MT_SAFE) + // Pass over both the Event_Handler *and* the mask in order to allow + // the caller to dictate which Event_Handler method the receiver + // invokes. + + n = this->notification_handler_.notify (eh, mask); +#else + eh = eh; + mask = mask; +#endif /* ACE_MT_SAFE */ + return n == -1 ? -1 : 0; +} + +int +ACE_Reactor::resume_handler (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Reactor::resume_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->resume (handle); +} + +int +ACE_Reactor::suspend_handler (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Reactor::suspend_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->suspend (handle); +} + +int +ACE_Reactor::suspend_handlers (void) +{ + ACE_TRACE ("ACE_Reactor::suspend_handlers"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + + ACE_Event_Handler *eh = 0; + + for (ACE_Handler_Repository_Iterator iter (this->handler_rep_); + iter.next (eh) != 0; + iter.advance ()) + this->suspend (eh->get_handle ()); + + return 0; +} + +int +ACE_Reactor::resume_handlers (void) +{ + ACE_TRACE ("ACE_Reactor::resume_handlers"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + + ACE_Event_Handler *eh = 0; + + for (ACE_Handler_Repository_Iterator iter (this->handler_rep_); + iter.next (eh) != 0; + iter.advance ()) + this->resume (eh->get_handle ()); + + return 0; +} + +int +ACE_Reactor::register_handler (ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::register_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->attach (handler->get_handle (), handler, mask); +} + +int +ACE_Reactor::register_handler (ACE_HANDLE handle, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::register_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->attach (handle, handler, mask); +} + +int +ACE_Reactor::register_handler (const ACE_Handle_Set &handles, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::register_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->register_handlers (handles, handler, mask); +} + +int +ACE_Reactor::handler (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Event_Handler **handler) +{ + ACE_TRACE ("ACE_Reactor::handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->handler_i (handle, mask, handler); +} + +int +ACE_Reactor::remove_handler (const ACE_Handle_Set &handles, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::remove_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->remove_handlers (handles, mask); +} + +int +ACE_Reactor::remove_handler (ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::remove_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->detach (handler->get_handle (), mask); +} + +int +ACE_Reactor::remove_handler (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::remove_handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->detach (handle, mask); +} + +// Performs operations on the "ready" bits. + +int +ACE_Reactor::ready_ops (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + int ops) +{ + ACE_TRACE ("ACE_Reactor::ready_ops"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->bit_ops (handle, mask, + this->rd_handle_mask_ready_, + this->wr_handle_mask_ready_, + this->ex_handle_mask_ready_, + ops); +} + +// Initialize the ACE_Reactor + +int +ACE_Reactor::open (size_t size, + int restart, + ACE_Sig_Handler *sh) +{ + ACE_TRACE ("ACE_Reactor::open"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + + if (this->initialized_ != 0) + return -1; + else + this->initialized_ = 1; + + this->owner_ = ACE_Thread::self (); + this->restart_ = restart; + + // Allows the signal handler to be overridden. + if (sh == 0) + { + ACE_NEW_RETURN (this->signal_handler_, ACE_Sig_Handler, -1); + this->delete_signal_handler_ = 1; + } + else + { + this->signal_handler_ = sh; + this->delete_signal_handler_ = 0; + } + + if (this->handler_rep_.open (size) == -1) + return -1; +#if defined (ACE_MT_SAFE) + else if (this->notification_handler_.open (this) == -1) + { + // Make sure to release resources. + this->handler_rep_.close (this); + return -1; + } +#endif /* ACE_MT_SAFE */ + + ACE_NEW_RETURN (this->timer_queue_, ACE_Timer_Queue, -1); + +#if defined (ACE_USE_POLL) + ACE_NEW_RETURN (this->poll_h_, pollfd[size], -1); + + for (size_t h = 0; h < size; h++) + { + this->poll_h_[h].fd = -1; + this->poll_h_[h].events = 0; + this->poll_h_[h].revents = 0; + } +#endif /* ACE_USE_POLL */ + + return 0; +} + +ACE_Reactor::ACE_Reactor (ACE_Sig_Handler *sh) + : timer_skew_ (0, ACE_TIMER_SKEW), + initialized_ (0), + timer_queue_ (0), + requeue_position_ (-1) // Requeue at end of waiters by default. +#if defined (ACE_MT_SAFE) + , token_ (*this) +#endif /* ACE_MT_SAFE */ +{ + ACE_TRACE ("ACE_Reactor::ACE_Reactor"); + if (this->open (ACE_Reactor::DEFAULT_SIZE, 0, sh)) + ACE_ERROR ((LM_ERROR, "%p\n", "open failed")); +} + +// Initialize the new ACE_Reactor. + +ACE_Reactor::ACE_Reactor (size_t size, int rs, ACE_Sig_Handler *sh) + : timer_skew_ (0, ACE_TIMER_SKEW), + initialized_ (0), + timer_queue_ (0), + requeue_position_ (-1) // Requeue at end of waiters by default. +#if defined (ACE_MT_SAFE) + , token_ (*this) +#endif /* ACE_MT_SAFE */ +{ + ACE_TRACE ("ACE_Reactor::ACE_Reactor"); + if (this->open (size, rs, sh) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "open failed")); +} + +// Close down the ACE_Reactor instance, detaching any remaining +// Event_Handers. This had better be called from the main event loop +// thread... + +void +ACE_Reactor::close (void) +{ + ACE_TRACE ("ACE_Reactor::close"); + ACE_MT (ACE_GUARD (ACE_REACTOR_MUTEX, ace_mon, this->token_)); + + if (this->timer_queue_ != 0) + { + this->handler_rep_.close (this); + + if (this->delete_signal_handler_) + delete this->signal_handler_; + this->signal_handler_ = 0; + + delete this->timer_queue_; + this->timer_queue_ = 0; + +#if defined (ACE_MT_SAFE) + this->notification_handler_.close (); +#endif /* ACE_MT_SAFE */ + +#if defined (ACE_USE_POLL) + delete [] this->poll_h_; +#endif /* ACE_USE_POLL */ + } +} + +ACE_Reactor::~ACE_Reactor (void) +{ + ACE_TRACE ("ACE_Reactor::~ACE_Reactor"); + this->close (); +} + +int +ACE_Reactor::remove_handlers (const ACE_Handle_Set &handles, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::remove_handlers"); + ACE_HANDLE h; + + for (ACE_Handle_Set_Iterator handle_iter (handles); + (h = handle_iter ()) != ACE_INVALID_HANDLE; + ++handle_iter) + if (this->detach (h, mask) == -1) + return -1; + + return 0; +} + +int +ACE_Reactor::register_handlers (const ACE_Handle_Set &handles, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::register_handlers"); + ACE_HANDLE h; + + for (ACE_Handle_Set_Iterator handle_iter (handles); + (h = handle_iter ()) != ACE_INVALID_HANDLE; + ++handle_iter) + if (this->attach (h, handler, mask) == -1) + return -1; + + return 0; +} + +int +ACE_Reactor::register_handler (const ACE_Sig_Set &sigset, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp) +{ + ACE_TRACE ("ACE_Reactor::register_handler"); + int result = 0; + + for (int s = 1; s < NSIG; s++) + if (sigset.is_member (s) + && this->signal_handler_->register_handler (s, new_sh, new_disp) == -1) + result = -1; + + return result; +} + +int +ACE_Reactor::remove_handler (const ACE_Sig_Set &sigset) +{ + ACE_TRACE ("ACE_Reactor::remove_handler"); + int result = 0; + + for (int s = 1; s < NSIG; s++) + if (sigset.is_member (s) + && this->signal_handler_->remove_handler (s) == -1) + result = -1; + + return result; +} + +// Note the queue handles its own locking. + +int +ACE_Reactor::schedule_timer (ACE_Event_Handler *handler, + const void *arg, + const ACE_Time_Value &delta_time, + const ACE_Time_Value &interval) +{ + ACE_TRACE ("ACE_Reactor::schedule_timer"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + + return this->timer_queue_->schedule + (handler, arg, ACE_OS::gettimeofday () + delta_time, interval); +} + +// Main event loop driver that blocks for <how_long> before returning +// (will return earlier if I/O or signal events occur). + +int +ACE_Reactor::handle_events (ACE_Time_Value &max_wait_time) +{ + ACE_TRACE ("ACE_Reactor::handle_events"); + + // Stash the current time. + ACE_Time_Value prev_time = ACE_OS::gettimeofday (); + + int result = this->handle_events (&max_wait_time); + + // Compute the time while the Reactor is processing. + ACE_Time_Value elapsed_time = ACE_OS::gettimeofday () - prev_time; + + if (max_wait_time > elapsed_time) + max_wait_time = max_wait_time - elapsed_time; + else + { + max_wait_time = ACE_Time_Value::zero; // Used all of timeout. + errno = ETIME; + } + return result; +} + +int +ACE_Reactor::handle_error (void) +{ + ACE_TRACE ("ACE_Reactor::handle_error"); + if (errno == EINTR) + return this->restart_; + else if (errno == EBADF) + return this->check_handles (); + else + return -1; +} + +void +ACE_Reactor::notify_handle (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Handle_Set &ready_mask, + ACE_Event_Handler *iop, + ACE_EH_PTMF ptmf) +{ + ACE_TRACE ("ACE_Reactor::notify_handle"); + if (iop == 0) + return; + + int status = (iop->*ptmf) (handle); + + if (status < 0) + this->detach (handle, mask); + else if (status > 0) + ready_mask.set_bit (handle); +} + +// Perform GET, CLR, SET, and ADD operations on the Handle_Sets. +// +// GET = 1, Retrieve current value +// SET = 2, Set value of bits to new mask (changes the entire mask) +// ADD = 3, Bitwise "or" the value into the mask (only changes +// enabled bits) +// CLR = 4 Bitwise "and" the negation of the value out of the mask +// (only changes enabled bits) +// +// Returns the original mask. Must be called with locks held. + +int +ACE_Reactor::bit_ops (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Handle_Set &rd, + ACE_Handle_Set &wr, + ACE_Handle_Set &ex, + int ops) +{ + ACE_TRACE ("ACE_Reactor::bit_ops"); + if (this->handler_rep_.invalid_handle (handle)) + return -1; + + ACE_Sig_Guard sb; // Block out all signals until method returns. + + ACE_FDS_PTMF ptmf = &ACE_Handle_Set::set_bit; + u_long omask = ACE_Event_Handler::NULL_MASK; + + switch (ops) + { + case ACE_Reactor::GET_MASK: + if (rd.is_set (handle)) + ACE_SET_BITS (omask, ACE_Event_Handler::READ_MASK); + if (wr.is_set (handle)) + ACE_SET_BITS (omask, ACE_Event_Handler::WRITE_MASK); + if (ex.is_set (handle)) + ACE_SET_BITS (omask, ACE_Event_Handler::EXCEPT_MASK); + break; + + case ACE_Reactor::CLR_MASK: + ptmf = &ACE_Handle_Set::clr_bit; + /* FALLTHRU */ + case ACE_Reactor::SET_MASK: + /* FALLTHRU */ + case ACE_Reactor::ADD_MASK: + + // The following code is rather subtle... Note that if we are + // doing a ACE_Reactor::SET_MASK then if the bit is not enabled + // in the mask we need to clear the bit from the ACE_Handle_Set. + // On the other hand, f we are doing a ACE_Reactor::CLR_MASK or + // a ACE_Reactor::ADD_MASK we just carry out the operations + // specified by the mask. + + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK)) + { + (rd.*ptmf) (handle); + ACE_SET_BITS (omask, ACE_Event_Handler::READ_MASK); + } + else if (ops == ACE_Reactor::SET_MASK) + rd.clr_bit (handle); + + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK)) + { + (wr.*ptmf) (handle); + ACE_SET_BITS (omask, ACE_Event_Handler::WRITE_MASK); + } + else if (ops == ACE_Reactor::SET_MASK) + wr.clr_bit (handle); + + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK)) + { + (ex.*ptmf) (handle); + ACE_SET_BITS (omask, ACE_Event_Handler::EXCEPT_MASK); + } + else if (ops == ACE_Reactor::SET_MASK) + ex.clr_bit (handle); + break; + default: + return -1; + } + return omask; +} + +// Perform GET, CLR, SET, and ADD operations on the select() +// Handle_Sets. +// +// GET = 1, Retrieve current value +// SET = 2, Set value of bits to new mask (changes the entire mask) +// ADD = 3, Bitwise "or" the value into the mask (only changes +// enabled bits) +// CLR = 4 Bitwise "and" the negation of the value out of the mask +// (only changes enabled bits) +// +// Returns the original mask. + +int +ACE_Reactor::mask_ops (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + int ops) +{ + ACE_TRACE ("ACE_Reactor::mask_ops"); + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + return this->bit_ops (handle, mask, + this->rd_handle_mask_, + this->wr_handle_mask_, + this->ex_handle_mask_, + ops); +} + +// Must be called with locks held + +int +ACE_Reactor::handler_i (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Event_Handler **handler) +{ + ACE_TRACE ("ACE_Reactor::handler_i"); + if (this->handler_rep_.invalid_handle (handle) + || this->handler_rep_.find (handle) == 0) + return -1; + else + { + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK) + && this->rd_handle_mask_.is_set (handle) == 0) + return -1; + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK) + && this->wr_handle_mask_.is_set (handle) == 0) + return -1; + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK) + && this->ex_handle_mask_.is_set (handle) == 0) + return -1; + } + + if (handler != 0) + *handler = this->handler_rep_.find (handle); + return 0; +} + +// Must be called with locks held + +int +ACE_Reactor::resume (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Reactor::resume"); + if (this->handler_rep_.invalid_handle (handle) + || this->handler_rep_.find (handle) == 0) + return -1; + + this->rd_handle_mask_.set_bit (handle); + this->wr_handle_mask_.set_bit (handle); + this->ex_handle_mask_.set_bit (handle); + return 0; +} + +// Must be called with locks held + +int +ACE_Reactor::suspend (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Reactor::suspend"); + if (this->handler_rep_.invalid_handle (handle) + || this->handler_rep_.find (handle) == 0) + return -1; + + this->rd_handle_mask_.clr_bit (handle); + this->wr_handle_mask_.clr_bit (handle); + this->ex_handle_mask_.clr_bit (handle); + return 0; +} + +// Must be called with locks held + +int +ACE_Reactor::attach (ACE_HANDLE handle, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::attach"); + + if (this->handler_rep_.invalid_handle (handle)) + return -1; + + this->handler_rep_.bind (handle, handler); + + this->bit_ops (handle, mask, + this->rd_handle_mask_, + this->wr_handle_mask_, + this->ex_handle_mask_, + ACE_Reactor::ADD_MASK); + return 0; +} + +int +ACE_Reactor::detach (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::detach"); + if (this->handler_rep_.invalid_handle (handle) + || this->handler_rep_.find (handle) == 0) + return -1; + + ACE_Event_Handler *eh = this->handler_rep_.find (handle); + + this->bit_ops (handle, mask, + this->rd_handle_mask_, + this->wr_handle_mask_, + this->ex_handle_mask_, + ACE_Reactor::CLR_MASK); + + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0) + eh->handle_close (handle, mask); + + // See if we can unbind this handle. + this->handler_rep_.unbind (handle, + this->rd_handle_mask_, + this->wr_handle_mask_, + this->ex_handle_mask_); + return 0; +} + +#if defined (ACE_USE_POLL) +// Transforms the select() data structures into a data structure +// suitable for use with poll(). + +pollfd * +ACE_Reactor::handle_sets_to_poll_fds (ACE_HANDLE &width) +{ + ACE_TRACE ("ACE_Reactor::handle_sets_to_poll_fds"); + + for (ACE_HANDLE h = 0; h < this->handler_rep_.max_handlep1 (); h++) + { + if (this->wr_handle_mask_.is_set (h)) + { + this->poll_h_[width].fd = h; + ACE_SET_BITS (this->poll_h_[width].events, ACE_Event_Handler::WRITE_MASK); + } + if (this->rd_handle_mask_.is_set (h)) + { + this->poll_h_[width].fd = h; + ACE_SET_BITS (this->poll_h_[width].events, ACE_Event_Handler::READ_MASK); + } + if (this->ex_handle_mask_.is_set (h)) + { + this->poll_h_[width].fd = h; + ACE_SET_BITS (this->poll_h_[width].events, ACE_Event_Handler::EXCEPT_MASK); + } + if (this->poll_h_[width].fd != -1) + width++; + } + + return this->poll_h_; + return 0; +} + +// Transforms the poll() data structures into data structures +// suitable for use with select(). + +void +ACE_Reactor::poll_fds_to_handle_sets (ACE_HANDLE width, + ACE_Handle_Set &rmask, + ACE_Handle_Set &wmask, + ACE_Handle_Set &emask, + int nfound) +{ + ACE_TRACE ("ACE_Reactor::poll_fds_to_handle_sets"); + + for (ACE_HANDLE h = 0; nfound > 0 && h < width; h++) + { + int found = 0; + pollfd &p_fd = this->poll_h_[h]; + + if (p_fd.revents & POLLOUT) + { + wmask.set_bit (p_fd.fd); + found = 1; + } + + if (p_fd.revents & POLLPRI) + { + emask.set_bit (p_fd.fd); + found = 1; + } + + if ((p_fd.revents & POLLIN) + || (p_fd.revents & POLLHUP) + || (p_fd.revents & POLLERR)) + { + rmask.set_bit (p_fd.fd); + found = 1; + } + + p_fd.revents = 0; + p_fd.events = 0; + p_fd.fd = -1; + + if (found) + nfound--; + } +} +#endif /* ACE_USE_POLL */ + +// Must be called with lock held + +int +ACE_Reactor::wait_for_multiple_events (ACE_Handle_Set &rmask, + ACE_Handle_Set &wmask, + ACE_Handle_Set &emask, + ACE_Time_Value *max_wait_time) +{ + ACE_TRACE ("ACE_Reactor::wait_for_multiple_events"); +#if defined (ACE_USE_POLL) + u_long width = 0; +#endif /* ACE_USE_POLL */ + int nfound; + + do + { + max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time); + +#if defined (ACE_USE_POLL) + pollfd *phandles = this->handle_sets_to_poll_fds (width); + nfound = ACE_OS::poll (phandles, width, max_wait_time); +#else /* USE SELECT */ + size_t width = this->handler_rep_.max_handlep1 (); + rmask = this->rd_handle_mask_; + wmask = this->wr_handle_mask_; + emask = this->ex_handle_mask_; + nfound = ACE_OS::select (int (width), rmask, wmask, emask, max_wait_time); +#endif /* ACE_USE_POLL */ + } + while (nfound == -1 && this->handle_error () > 0); + +#if defined (ACE_USE_POLL) + this->poll_fds_to_handle_sets (width, rmask, wmask, emask, nfound); +#endif /* ACE_USE_POLL */ + + if (nfound > 0) + { +#if !defined (ACE_WIN32) + rmask.sync (this->handler_rep_.max_handlep1 ()); + wmask.sync (this->handler_rep_.max_handlep1 ()); + emask.sync (this->handler_rep_.max_handlep1 ()); +#endif /* ACE_REACTOR_ALTERANTIVE_IMPL */ + } + return nfound; // Timed out or input available +} + +void +ACE_Reactor::dispatch (int nfound, + ACE_Handle_Set &rmask, + ACE_Handle_Set &wmask, + ACE_Handle_Set &emask) +{ + ACE_TRACE ("ACE_Reactor::dispatch"); + // Handle timers first since they may have higher latency + // constraints... + + if (!this->timer_queue_->is_empty ()) + // Fudge factor accounts for problems with Solaris timers... + this->timer_queue_->expire (ACE_OS::gettimeofday () + this->timer_skew_); + +#if defined (ACE_MT_SAFE) + // Check to see if the notify ACE_HANDLE is enabled. If so, it + // means that one or more other threads are trying to update the + // ACE_Reactor's internal tables. We'll handle all these threads + // and then break out to continue the event loop. + + if (this->notification_handler_.handle_notifications (rmask) == 0) +#endif /* ACE_MT_SAFE */ + { + ACE_HANDLE h; + + if (nfound > 0) + { + // Handle output conditions (this code needs to come first to + // handle the obscure case of piggy-backed data coming along + // with the final handshake message of a nonblocking + // connection). + + for (ACE_Handle_Set_Iterator handle_iter_wr (wmask); + (h = handle_iter_wr ()) != ACE_INVALID_HANDLE && --nfound >= 0; + ++handle_iter_wr) + this->notify_handle (h, ACE_Event_Handler::WRITE_MASK, + this->wr_handle_mask_ready_, + this->handler_rep_.find (h), + &ACE_Event_Handler::handle_output); + } + + if (nfound > 0) + { + // Handle "exceptional" conditions. + for (ACE_Handle_Set_Iterator handle_iter_ex (emask); + (h = handle_iter_ex ()) != ACE_INVALID_HANDLE && --nfound >= 0; + ++handle_iter_ex) + this->notify_handle (h, ACE_Event_Handler::EXCEPT_MASK, + this->ex_handle_mask_ready_, + this->handler_rep_.find (h), + &ACE_Event_Handler::handle_exception); + } + if (nfound > 0) + { + // Handle input and shutdown conditions. + for (ACE_Handle_Set_Iterator handle_iter_rd (rmask); + (h = handle_iter_rd ()) != ACE_INVALID_HANDLE && --nfound >= 0; + ++handle_iter_rd) + this->notify_handle (h, ACE_Event_Handler::READ_MASK, + this->rd_handle_mask_ready_, + this->handler_rep_.find (h), + &ACE_Event_Handler::handle_input); + } + } +} + +int +ACE_Reactor::fill_in_ready (ACE_Handle_Set &rmask, + ACE_Handle_Set &wmask, + ACE_Handle_Set &emask) +{ + ACE_TRACE ("ACE_Reactor::fill_in_ready"); + ACE_Sig_Guard sb; + + rmask = this->rd_handle_mask_ready_; + wmask = this->wr_handle_mask_ready_; + emask = this->ex_handle_mask_ready_; + + this->rd_handle_mask_ready_.reset (); + this->wr_handle_mask_ready_.reset (); + this->ex_handle_mask_ready_.reset (); + + return rmask.num_set () + wmask.num_set () + emask.num_set (); +} + +int +ACE_Reactor::handle_events (ACE_Time_Value *max_wait_time) +{ + ACE_TRACE ("ACE_Reactor::handle_events"); +#if defined (ACE_MT_SAFE) + ACE_MT (ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1)); + if (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_) == 0) + return -1; +#endif /* ACE_MT_SAFE */ + + ACE_Handle_Set rmask; + ACE_Handle_Set wmask; + ACE_Handle_Set emask; + int nfound; + + if (this->any_ready ()) + nfound = this->fill_in_ready (rmask, wmask, emask); + else + nfound = this->wait_for_multiple_events (rmask, wmask, emask, max_wait_time); + + for (;;) + { + this->dispatch (nfound, rmask, wmask, emask); + + if (ACE_Sig_Handler::sig_pending () != 0) + { + ACE_Sig_Handler::sig_pending (0); + + // Dispatch any HANDLES that are activated + // as a result of signals since they may be + // time critical... + + if (this->any_ready ()) + { + nfound = this->fill_in_ready (rmask, wmask, emask); + continue; + } + } + break; + } + + return nfound; +} + +int +ACE_Reactor::check_handles (void) +{ + ACE_TRACE ("ACE_Reactor::check_handles"); + +#if defined (ACE_USE_POLL) + pollfd p_handle; + p_handle.events = POLLIN; +#else + ACE_Time_Value time_poll = ACE_Time_Value::zero; + ACE_Handle_Set rmask; +#endif /* ACE_USE_POLL */ + + ACE_Event_Handler *eh = 0; + int result = 0; + + for (ACE_Handler_Repository_Iterator iter (this->handler_rep_); + iter.next (eh) != 0; + iter.advance ()) + { + ACE_HANDLE handle = eh->get_handle (); + + // Skip back to the beginning of the loop if the HANDLE is + // invalid. + if (handle == ACE_INVALID_HANDLE) + continue; + +#if defined (ACE_USE_POLL) + p_handle.fd = handle; + if (ACE_OS::poll (&p_handle, 1, 0) == -1) + { + result = 1; + this->detach (handle, ACE_Event_Handler::RWE_MASK); + } +#else + rmask.set_bit (handle); + if (ACE_OS::select (int (handle) + 1, + rmask, 0, 0, + &time_poll) < 0) + { + result = 1; + this->detach (handle, ACE_Event_Handler::RWE_MASK); + } + rmask.clr_bit (handle); +#endif /* ACE_USE_POLL */ + } + + return result; +} diff --git a/ace/Reactor.h b/ace/Reactor.h new file mode 100644 index 00000000000..fe178877950 --- /dev/null +++ b/ace/Reactor.h @@ -0,0 +1,642 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Reactor.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_REACTOR_H) +#define ACE_REACTOR_H + +#include "ace/Handle_Set.h" +#include "ace/Timer_Queue.h" +#include "ace/Signal.h" +#include "ace/Thread.h" +#include "ace/Token.h" +#include "ace/Pipe.h" +#include "ace/SOCK_Stream.h" + +// Add useful typedefs to simplify the following code. +typedef void (ACE_Handle_Set::*ACE_FDS_PTMF) (ACE_HANDLE); +typedef int (ACE_Event_Handler::*ACE_EH_PTMF) (ACE_HANDLE); + +// Forward declaration. +class ACE_Reactor; + +#if defined (ACE_MT_SAFE) + +// The following two classes have to be moved out here to keep the SGI +// C++ compiler happy (it doesn't like nested classes). + +class ACE_Export ACE_Notification_Handler : public ACE_Event_Handler + // = TITLE + // Callback and unblock the ACE_Reactor if it's sleeping. + // + // = DESCRIPTION + // This implementation is necessary for cases where the Reactor + // is being run in a multi-threaded program. In this case, we + // need a special trick to unblock select() or poll() when + // updates occur in somewhere other than the main ACE_Reactor + // thread. All we do is write data to a pipe or socket that the + // ACE_Reactor is listening on. +{ +public: + // = Initialization and termination methods. + int open (ACE_Reactor *); + int close (void); + + int handle_notifications (ACE_Handle_Set &rmask); + // Handles pending threads (if any) that are waiting to unblock the + // Reactor. + + ssize_t notify (ACE_Event_Handler * = 0, + ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK); + // Called by a thread when it wants to unblock the Reactor. + + virtual int handle_input (ACE_HANDLE handle); + // Called back by the Reactor when a thread wants to unblock us. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Reactor *reactor_; + // Keep a back pointer to the Reactor. + + ACE_Pipe notification_pipe_; + // Contains the HANDLE the Reactor is listening on, as well as the + // HANDLE that threads wanting the attention of the Reactor will + // write to. +}; + +#if defined (ACE_REACTOR_HAS_DEADLOCK_DETECTION) +#include "ace/Local_Tokens.h" +typedef ACE_Local_Mutex ACE_REACTOR_MUTEX; +#else +typedef ACE_Token ACE_REACTOR_MUTEX; +#endif /* ACE_REACTOR_HAS_DEADLOCK_DETECTION */ + +class ACE_Export ACE_Reactor_Token : public ACE_REACTOR_MUTEX + // = TITLE + // Used as a synchronization mechanism to coordinate concurrent + // access to a Reactor object. +{ +public: + ACE_Reactor_Token (ACE_Reactor &r); + + virtual void sleep_hook (void); + // Called just before the ACE_Event_Handler goes to sleep. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Reactor &reactor_; +}; + +#endif /* ACE_MT_SAFE */ + +class ACE_Export ACE_Handler_Repository +{ + // = TITLE + // Used to map ACE_HANDLEs onto the appropriate ACE_Event_Handler *. + // + // = DESCRIPTION + // This class is necessary to shield differences between UNIX + // and WIN32. In UNIX, ACE_HANDLE is an int, whereas in WIN32 + // it's a void *. This class hides all these details from the + // bulk of the Reactor code. +public: + friend class ACE_Handler_Repository_Iterator; + + // = Initialization and termination methods. + ACE_Handler_Repository (void); + // Default "do-nothing" constructor. + + int open (size_t size); + // Initialize a repository of the appropriate <size>. + + int close (ACE_Reactor *); + // Destroy the handler and cleanup the Reactor. + + // = Search structure operations. + + ACE_Event_Handler *find (ACE_HANDLE); + // Return the <ACE_Event_Handler *> associated with <ACE_HANDLE>. + + int bind (ACE_HANDLE, ACE_Event_Handler *); + // Bind the <ACE_Event_Handler *> to the <ACE_HANDLE>. + + int unbind (ACE_HANDLE, ACE_Handle_Set &rd_mask, + ACE_Handle_Set &wr_mask, ACE_Handle_Set &ex_mask); + // Remove the binding of <ACE_HANDLE>. + + // Performs sanity checking on the ACE_HANDLE. + int invalid_handle (ACE_HANDLE); + + size_t max_handlep1 (void); + // Maximum ACE_HANDLE value, plus 1. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ssize_t max_size_; + // Maximum number of handles. + +#if defined (ACE_WIN32) + ssize_t cur_size_; + // The highest currently active handle, plus 1. + + // = This structure maps <HANDLES> to <Event_Handlers>. + struct ACE_NT_EH_Record + { + ACE_HANDLE handle_; + ACE_Event_Handler *event_handler_; + }; + + ACE_NT_EH_Record *event_handlers_; + // The NT version implements this via a dynamically allocated + // array of <ACE_NT_EH_Record *>. Since NT implements ACE_HANDLE + // as a void * we can't directly index into this array. Therefore, + // we just do a linear search (for now). Next, we'll modify + // things to use hashing or something faster... +#else + ACE_HANDLE max_handlep1_; + // The highest currently active handle, plus 1. + + ACE_Event_Handler **event_handlers_; + // The UNIX version implements this via a dynamically allocated + // array of <ACE_Event_Handler *> that is indexed directly using + // the ACE_HANDLE value. +#endif /* ACE_WIN32 */ +}; + +class ACE_Export ACE_Handler_Repository_Iterator +{ +public: + // = Initialization method. + ACE_Handler_Repository_Iterator (const ACE_Handler_Repository &s); + + // = Iteration methods. + + int next (ACE_Event_Handler *&next_item); + // Pass back the <next_item> that hasn't been seen in the Set. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const ACE_Handler_Repository &rep_; + // Reference to the Handler_Repository we are iterating over. + + ssize_t current_; + // Pointer to the current iteration level. +}; + +class ACE_Export ACE_Reactor + // = TITLE + // An object oriented event demultiplexor and event handler + // dispatcher. + // + // = DESCRIPTION + // The ACE_Reactor is an object-oriented event demultiplexor + // and event handler dispatcher. The sources of events that the + // ACE_Reactor waits for and dispatches includes I/O events, + // signals, and timer events. +{ +public: + enum + { + DEFAULT_SIZE = ACE_DEFAULT_REACTOR_SIZE, + // Default size of the Reactor's handle table. + + // = Operations on the "ready" mask and the "dispatch" mask. + GET_MASK = 1, + // Retrieve current value of the the "ready" mask or the "dispatch" mask. + SET_MASK = 2, + // Set value of bits to new mask (changes the entire mask). + ADD_MASK = 3, + // Bitwise "or" the value into the mask (only changes enabled bits). + CLR_MASK = 4 + // Bitwise "and" the negation of the value out of the mask (only changes enabled bits). + }; + + // = Initialization and termination methods. + + ACE_Reactor (ACE_Sig_Handler * = 0); + // Initialize the new ACE_Reactor with the default size. + + ACE_Reactor (size_t size, + int restart = 0, + ACE_Sig_Handler * = 0); + // Initialize the new ACE_Reactor of size <size>. + + virtual int open (size_t size = DEFAULT_SIZE, + int restart = 0, + ACE_Sig_Handler * = 0); + // Initialize the new ACE_Reactor of size <size>. + + virtual void close (void); + // Close down the reactor and release all of its resources. + + virtual ~ACE_Reactor (void); + // Close down the reactor and release all of its resources. + + // = Timer management. + virtual int schedule_timer (ACE_Event_Handler *, + const void *arg, + const ACE_Time_Value &delta, + const ACE_Time_Value &interval = ACE_Time_Value::zero); + // Schedule an <event_handler> that will expire after <delay> amount + // of time. If it expires then <arg> is passed in as the value to + // the <event_handler>'s <handle_timeout> callback method. If + // <interval> is != to <ACE_Time_Value::zero> then it is used to + // reschedule the <event_handler> automatically. This method + // returns a timer handle that uniquely identifies the + // <event_handler> in an internal list. This timer handle can be + // used to cancel an <event_handler> before it expires. The + // cancellation ensures that timer_ids are unique up to values of + // greater than 2 billion timers. As long as timers don't stay + // around longer than this there should be no problems with + // accidentally deleting the wrong timer. + + virtual int cancel_timer (ACE_Event_Handler *event_handler); + // Cancel all <event_handlers> that match the address of + // <event_handler>. + + virtual int cancel_timer (int timer_id, const void **arg = 0); + // Cancel the single <ACE_Event_Handler> that matches the <timer_id> + // value (which was returned from the <schedule> method). If arg is + // non-NULL then it will be set to point to the ``magic cookie'' + // argument passed in when the <Event_Handler> was registered. This + // makes it possible to free up the memory and avoid memory leaks. + + // = Event loop drivers. + virtual int handle_events (ACE_Time_Value *how_long = 0); + // Main event loop driver that blocks for <how_long> before + // returning (will return earlier if I/O or signal events occur). + // Note that <how_long> can be 0, in which case this method blocks + // until I/O events or signals occur. + + virtual int handle_events (ACE_Time_Value &how_long); + // Main event loop driver that blocks for <how_long> before + // returning (will return earlier if I/O or signal events occur). + + // = Register and remove Handlers. + virtual int register_handler (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // Register an Event_Handler <eh> with a particular <mask>. Note + // that the Reactor will call eh->get_handle() to extract the + // underlying I/O handle). + + virtual int register_handler (ACE_HANDLE handle, + ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // Register an Event_Handler <eh> with a particular <mask>. Note + // that since the <handle> is given the Reactor will *not* call + // eh->get_handle() to extract the underlying I/O handle). + + virtual int register_handler (const ACE_Handle_Set &handles, + ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // Register <eh> with all the <handles> in the <Handle_Set>. + + virtual int register_handler (int signum, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp = 0, + ACE_Event_Handler **old_sh = 0, + ACE_Sig_Action *old_disp = 0); + // Register <new_sh> to handle the signal <signum> using the + // <new_disp>. Returns the <old_sh> that was previously registered + // (if any), along with the <old_disp> of the signal handler. + + virtual int register_handler (const ACE_Sig_Set &sigset, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp = 0); + // Registers <new_sh> to handle a set of signals <sigset> using the + // <new_disp>. + + virtual int remove_handler (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // Removes the <mask> binding of <eh> from the Reactor. If there + // are no more bindings for this <eh> then it is removed from the + // Reactor. Note that the Reactor will call eh->get_handle() to + // extract the underlying I/O handle. + + virtual int remove_handler (ACE_HANDLE handle, + ACE_Reactor_Mask); + // Removes the <mask> bind of <Event_Handler> whose handle is + // <handle> from the Reactor. If there are no more bindings for + // this <eh> then it is removed from the Reactor. + + virtual int remove_handler (const ACE_Handle_Set &handle_set, + ACE_Reactor_Mask); + // Removes all the <mask> bindings for handles in the <handle_set> + // bind of <Event_Handler>. If there are no more bindings for any + // of these handlers then they are removed from the Reactor. + + virtual int remove_handler (int signum, + ACE_Sig_Action *new_disp, + ACE_Sig_Action *old_disp = 0, + int sigkey = -1); + // Remove the ACE_Event_Handler currently associated with <signum>. + // <sigkey> is ignored in this implementation since there is only + // one instance of a signal handler. Install the new disposition + // (if given) and return the previous disposition (if desired by the + // caller). Returns 0 on success and -1 if <signum> is invalid. + + virtual int remove_handler (const ACE_Sig_Set &sigset); + // Calls <remove_handler> for every signal in <sigset>. + + // = Suspend and resume Handlers. + + virtual int suspend_handler (ACE_Event_Handler *eh); + // Temporarily suspend the <Event_Handler> associated with <eh>. + + virtual int suspend_handler (ACE_HANDLE handle); + // Temporarily suspend the <Event_Handler> associated with <handle>. + + virtual int resume_handler (ACE_Event_Handler *eh); + // Resume a temporarily suspend <Event_Handler> associated with + // <eh>. + + virtual int resume_handler (ACE_HANDLE handle); + // Resume a temporarily suspended <Event_Handler> associated with + // <handle>. + + virtual int suspend_handlers (void); + // Suspend all the <Event_Handlers> in the Reactor. + + virtual int resume_handlers (void); + // Resume all the <Event_Handlers> in the Reactor. + + // = Misc. Handler operations. + virtual int handler (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Event_Handler **eh = 0); + // Check to see if <handle> is associated with a valid Event_Handler + // bound to <mask>. Return the <eh> associated with this <handler> + // if <eh> != 0. + + virtual int handler (int signum, + ACE_Event_Handler ** = 0); + // Check to see if <signum> is associated with a valid Event_Handler + // bound to a signal. Return the <eh> associated with this + // <handler> if <eh> != 0. + + // = High-level Event_Handler scheduling operations + + virtual int schedule_wakeup (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // ADD the dispatch MASK "bit" bound with the <eh> and the <mask>. + + virtual int schedule_wakeup (ACE_HANDLE handle, + ACE_Reactor_Mask mask); + // ADD the dispatch MASK "bit" bound with the <handle> and the <mask>. + + virtual int cancel_wakeup (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // CLR the dispatch MASK "bit" bound with the <eh> and the <mask>. + + virtual int cancel_wakeup (ACE_HANDLE handle, + ACE_Reactor_Mask mask); + // CLR the dispatch MASK "bit" bound with the <handle> and the <mask>. + + // = Low-level dispatch mask manipulation methods. + virtual int mask_ops (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask, + int ops); + // GET/SET/ADD/CLR the dispatch MASK "bit" bound with the <eh> and + // <mask>. + + virtual int mask_ops (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + int ops); + // GET/SET/ADD/CLR the dispatch MASK "bit" bound with the <handle> + // and <mask>. + + // = Ready bit manipulation methods. + virtual int ready_ops (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask, + int ops); + // GET/SET/ADD/CLR the ready "bit" bound with the <eh> and <mask>. + + virtual int ready_ops (ACE_HANDLE handle, + ACE_Reactor_Mask, + int ops); + // GET/SET/ADD/CLR the ready "bit" bound with the <handle> and <mask>. + + virtual int notify (ACE_Event_Handler * = 0, + ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK); + // Wakeup ACE_Reactor if currently blocked in select()/poll(). Pass + // over both the Event_Handler *and* the mask in order to allow the + // caller to dictate which Event_Handler method the receiver + // invokes. + + // = Get/set position that the main ACE_Reactor thread is requeued + // in the list of waiters during a notify() callback. + void requeue_position (int); + int requeue_position (void); + + // = Get/set the current "owner" of the thread (i.e., the only + // thread that can perform a handle_events()). + void owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0); + // Set the new owner of the thread and return the old owner. + + int owner (ACE_thread_t *); + // Return the current owner of the thread. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Internal methods that do the actual work (most of these + // assume that locks are held). + + virtual int attach (ACE_HANDLE handle, + ACE_Event_Handler *eh, + ACE_Reactor_Mask mask); + // Do the work of actually binding the <handle> and <eh> with the + // <mask>. + + virtual int detach (ACE_HANDLE handle, + ACE_Reactor_Mask); + // Do the work of actually unbinding the <handle> and <eh> with the + // <mask>. + + virtual int suspend (ACE_HANDLE handle); + // Suspend the <Event_Handler> associated with <handle> + virtual int resume (ACE_HANDLE handle); + // Resume the <Event_Handler> associated with <handle> + + virtual int remove_handlers (const ACE_Handle_Set &handles, + ACE_Reactor_Mask); + // Remove a set of <handles>. + + virtual int register_handlers (const ACE_Handle_Set &handles, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask); + // Register a set of <handles>. + + virtual int handler_i (ACE_HANDLE handle, + ACE_Reactor_Mask, + ACE_Event_Handler ** = 0); + // Implement the public <handler> method. + + virtual int handler_i (int signum, ACE_Event_Handler ** = 0); + // Implement the public <handler> method. + + virtual int any_ready (void) const; + + virtual int handle_error (void); + // Take corrective action when errors occur. + + virtual int check_handles (void); + // Make sure the handles are all valid. + + virtual int bit_ops (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Handle_Set &rd, + ACE_Handle_Set &wr, + ACE_Handle_Set &ex, + int ops); + // Allow manipulation of the dispatch mask and ready ops mask. + + virtual int fill_in_ready (ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Handle_Set &); + // Check if there are any bits enabled in the ready_ops set. + + virtual int wait_for_multiple_events (ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Time_Value *); + // Wait for events to occur. + + virtual void dispatch (int, + ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Handle_Set &); + // Dispatch timers and I/O event handlers once events have occurred. + + virtual void notify_handle (ACE_HANDLE handle, + ACE_Reactor_Mask mask, + ACE_Handle_Set &, + ACE_Event_Handler *eh, + ACE_EH_PTMF callback); + // Notify the appropriate <callback> in the context of the <eh> + // associated with <handle> that a particular event has occurred. + + ACE_Timer_Queue *timer_queue_; + // Defined as a pointer to allow overriding by derived classes... + + ACE_Handler_Repository handler_rep_; + // Pointer to an array of <ACE_Event_Handler *>s used to keep track + // of the user-defined callbacks. + + ACE_Sig_Handler *signal_handler_; + // Handle signals without requiring global/static variables. + + int delete_signal_handler_; + // Keeps track of whether we should delete the signal handler. + + // = Track which handles we are interested + // for various types of (reading, writing, and exception) events. + // The following three <Handle_Sets> are waited for by poll() or + // select(). + ACE_Handle_Set rd_handle_mask_; + ACE_Handle_Set wr_handle_mask_; + ACE_Handle_Set ex_handle_mask_; + + // = Keep track of events that we'd like to have dispatched + // *without* requiring poll() or select() to wait... + ACE_Handle_Set rd_handle_mask_ready_; + ACE_Handle_Set wr_handle_mask_ready_; + ACE_Handle_Set ex_handle_mask_ready_; + + int restart_; + // Restart automatically when interrupted + + int requeue_position_; + // Position that the main ACE_Reactor thread is requeued in the list + // of waiters during a notify() callback. If this value == -1 we + // are requeued at the end of the list. Else if it's 0 then we are + // requeued at the front of the list. Else if it's > 1 then that + // indicates the number of waiters to skip over. + + int initialized_; + // True if we've been initialized yet... + + ACE_thread_t owner_; + // The original thread that created this Reactor. + +#if defined (ACE_MT_SAFE) + ACE_Notification_Handler notification_handler_; + // Callback object that unblocks the ACE_Reactor if it's sleeping. + + ACE_Reactor_Token token_; + // Synchronization token for the MT_SAFE ACE_Reactor. + + void renew (void); + // Enqueue ourselves into the list of waiting threads at the + // appropriate point specified by <requeue_position_>. + + friend class ACE_Notification_Handler; +#endif /* ACE_MT_SAFE */ + + friend class ACE_Handler_Repository; + +#if defined (ACE_USE_POLL) + // = Convert to and from the select() to poll() types. + pollfd *handle_sets_to_poll_fds (ACE_HANDLE &width); + void poll_fds_to_handle_sets (ACE_HANDLE width, + ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Handle_Set &, + int nfound); + pollfd *poll_h_; + // Pointer to the array of pollfd handles for poll() version. +#endif /* ACE_USE_POLL */ + +private: + ACE_Time_Value timer_skew_; + // Adjusts for skew that occurs in certain OS timers (e.g., + // Solaris). + + // Deny access since member-wise won't work... + ACE_Reactor (const ACE_Reactor &); + ACE_Reactor &operator = (const ACE_Reactor &); +}; + +#include "ace/Reactor.i" +#endif /* ACE_REACTOR_H */ diff --git a/ace/Reactor.i b/ace/Reactor.i new file mode 100644 index 00000000000..519b3fadccf --- /dev/null +++ b/ace/Reactor.i @@ -0,0 +1,135 @@ +/* -*- C++ -*- */ +// $Id$ + +// Reactor.i + +#include "ace/Log_Msg.h" + +inline int +ACE_Reactor::resume_handler (ACE_Event_Handler *h) +{ + ACE_TRACE ("ACE_Reactor::resume_handler"); + return this->resume (h->get_handle ()); +} + +inline int +ACE_Reactor::suspend_handler (ACE_Event_Handler *h) +{ + ACE_TRACE ("ACE_Reactor::suspend_handler"); + return this->suspend (h->get_handle ()); +} + +inline int +ACE_Reactor::register_handler (int signum, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp, + ACE_Event_Handler **old_sh, + ACE_Sig_Action *old_disp) +{ + ACE_TRACE ("ACE_Reactor::register_handler"); + return this->signal_handler_->register_handler (signum, + new_sh, new_disp, + old_sh, old_disp); +} + +inline int +ACE_Reactor::handler (int signum, ACE_Event_Handler **handler) +{ + ACE_TRACE ("ACE_Reactor::handler"); + return this->handler_i (signum, handler); +} + +inline int +ACE_Reactor::remove_handler (int signum, + ACE_Sig_Action *new_disp, + ACE_Sig_Action *old_disp, + int sigkey) +{ + ACE_TRACE ("ACE_Reactor::remove_handler"); + return this->signal_handler_->remove_handler (signum, new_disp, old_disp, sigkey); +} + +// The remaining methods in this file must be called with locks held + +// Note the queue handles its own locking. + +inline int +ACE_Reactor::cancel_timer (ACE_Event_Handler *handler) +{ + ACE_TRACE ("ACE_Reactor::cancel_timer"); + return this->timer_queue_->cancel (handler); +} + +inline int +ACE_Reactor::cancel_timer (int timer_id, const void **arg) +{ + ACE_TRACE ("ACE_Reactor::cancel_timer"); + return this->timer_queue_->cancel (timer_id, arg); +} + +// Performs operations on the "ready" bits. + +inline int +ACE_Reactor::ready_ops (ACE_Event_Handler *handler, + ACE_Reactor_Mask mask, + int ops) +{ + ACE_TRACE ("ACE_Reactor::ready_ops"); + return this->ready_ops (handler->get_handle (), mask, ops); +} + +// Performs operations on the "dispatch" masks. + +inline int +ACE_Reactor::mask_ops (ACE_Event_Handler *handler, + ACE_Reactor_Mask mask, + int ops) +{ + ACE_TRACE ("ACE_Reactor::mask_ops"); + return this->mask_ops (handler->get_handle (), mask, ops); +} + +inline int +ACE_Reactor::any_ready (void) const +{ + ACE_TRACE ("ACE_Reactor::any_ready"); + ACE_Sig_Guard sb; + + int result = this->rd_handle_mask_ready_.num_set () > 0 + || this->wr_handle_mask_ready_.num_set () > 0 + || this->ex_handle_mask_ready_.num_set () > 0; + + return result; +} + +inline int +ACE_Reactor::schedule_wakeup (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::schedule_wakeup"); + return this->mask_ops (eh->get_handle (), mask, ACE_Reactor::ADD_MASK); +} + +inline int +ACE_Reactor::cancel_wakeup (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::cancel_wakeup"); + return this->mask_ops (eh->get_handle (), mask, ACE_Reactor::CLR_MASK); +} + +inline int +ACE_Reactor::schedule_wakeup (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::schedule_wakeup"); + return this->mask_ops (handle, mask, ACE_Reactor::ADD_MASK); +} + +inline int +ACE_Reactor::cancel_wakeup (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_Reactor::cancel_wakeup"); + return this->mask_ops (handle, mask, ACE_Reactor::CLR_MASK); +} diff --git a/ace/ReactorEx.cpp b/ace/ReactorEx.cpp new file mode 100644 index 00000000000..6a55493a11b --- /dev/null +++ b/ace/ReactorEx.cpp @@ -0,0 +1,282 @@ +// ReactorEx.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/ReactorEx.h" + +#if defined (ACE_WIN32) + +#if !defined (__ACE_INLINE__) +#include "ace/ReactorEx.i" +#endif /* __ACE_INLINE__ */ + +ACE_ReactorEx::ACE_ReactorEx (void) + : active_handles_ (0), + timer_skew_ (0, ACE_TIMER_SKEW), + token_ (*this) +{ + if (this->register_handler (&this->notify_handler_) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "registering notify handler")); +} + +ACE_ReactorEx::~ACE_ReactorEx (void) +{ +} + +int +ACE_ReactorEx::notify (void) +{ + ACE_GUARD_RETURN (ACE_ReactorEx_Token, ace_mon, this->token_, -1); + + return notify_handler_.notify (); +} + +int +ACE_ReactorEx::register_handler (ACE_Event_Handler *eh, + ACE_HANDLE handle) +{ + ACE_GUARD_RETURN (ACE_ReactorEx_Token, ace_mon, this->token_, -1); + + if (this->active_handles_ >= ACE_ReactorEx::MAX_SIZE) + return -1; + + if (handle == ACE_INVALID_HANDLE) + handle = eh->get_handle (); + this->handles_[this->active_handles_] = handle; + this->handlers_[this->active_handles_] = eh; + this->active_handles_++; + return 0; +} + +// Removes -eh- from the ReactorEx. Note that the ReactorEx will call +// eh->get_handle() to extract the underlying I/O handle. + +int +ACE_ReactorEx::remove_handler (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask) +{ + ACE_GUARD_RETURN (ACE_ReactorEx_Token, ace_mon, this->token_, -1); + + ACE_HANDLE handle = eh->get_handle (); + + // Go through all the handles looking for -handle-. Even if we find + // it, we continue through the rest of the list. -handle- could + // appear multiple times. + for (size_t index = 0; index < this->active_handles_; index++) + { + if (this->handles_[index] == handle) + { + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0) + handlers_[index]->handle_close (handle, + ACE_Event_Handler::NULL_MASK); + + // If there was only one handle, reset the pointer to 0. + if (this->active_handles_ == 1) + { + // This is logically correct, but probably should never + // happen. This means that ACE_ReactorEx_Notify is + // being removed! We'll do it anyway and print out a + // warning. + this->active_handles_ = 0; + ACE_ERROR ((LM_ERROR, "ReactorEx: ReactorEx_Notify was" + "just removed!\n")); + } + // Otherwise, take the handle and handler from the back and + // overwrite the ones being removed. + else + { + this->handles_[index] = this->handles_[--this->active_handles_]; + this->handlers_[index] = this->handlers_[this->active_handles_]; + } + } + } + + return 0; +} + +int +ACE_ReactorEx::schedule_timer (ACE_Event_Handler *handler, + const void *arg, + const ACE_Time_Value &delta_time, + const ACE_Time_Value &interval) +{ + ACE_TRACE ("ACE_ReactorEx::schedule_timer"); + + return this->timer_queue_.schedule + (handler, arg, ACE_OS::gettimeofday () + delta_time, interval); +} + +int +ACE_ReactorEx::handle_events (ACE_Time_Value *how_long, + int wait_all) +{ + // @@ Need to implement -wait_all-. + + DWORD wait_status; + int handles_skipped = 0; + // These relative_things are moved through the handles_ each time + // handle_events is called. Set relative index = -1 so we can check + // in case of timeouts. + int relative_index = -1; + ACE_HANDLE *relative_handles = this->handles_; + ACE_Event_Handler **relative_handlers = this->handlers_; + + // Stash the current time. + ACE_Time_Value prev_time = ACE_OS::gettimeofday (); + // Check for pending timeout events. + how_long = timer_queue_.calculate_timeout (how_long); + // Translate into Win32 time value. + int timeout = how_long == 0 ? INFINITE : how_long->msec (); + + int active_handles = this->active_handles_; + + while (active_handles > 0) + { + wait_status = ::WaitForMultipleObjects (active_handles, + relative_handles, + wait_all, + timeout); + if (!this->timer_queue_.is_empty ()) + // Fudge factor accounts for problems with Solaris timers... + this->timer_queue_.expire (ACE_OS::gettimeofday () + this->timer_skew_); + + // Compute the time while the ReactorEx was processing. + ACE_Time_Value elapsed_time = ACE_OS::gettimeofday () - prev_time; + + // Update -how_long- to reflect the amount of time since + // handle_events was called. This is computed in case we return + // from the switch. + if (how_long != 0) + { + if (*how_long > elapsed_time) + *how_long = *how_long - elapsed_time; + else + *how_long = ACE_Time_Value::zero; // Used all of timeout. + } + + switch (wait_status) + { + case WAIT_TIMEOUT: + errno = ETIME; + // If we timed out on the first call, return 0, otherwise + // an event must have occured; return 1. + return relative_index == -1 ? 0 : 1; + case WAIT_FAILED: + errno = ::GetLastError (); + return -1; + default: + { + // @@ Need to implement WAIT_ABANDONED_0 stuff. + relative_index = wait_status - WAIT_OBJECT_0; + + if (relative_handlers[relative_index]->handle_signal (0) == -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. + this->remove_handler (relative_handlers[relative_index]); + else + // If we did not remove the handler, then move the index + // up one so that we skip this handler on the next + // iteration. + relative_index++; + + // Update the relative pointers. + relative_handles = &relative_handles[relative_index]; + relative_handlers = &relative_handlers[relative_index]; + + // The number of remaining active handles is + // active_handles_ less the number of handles we skipped + // over. + handles_skipped += relative_index; + active_handles = this->active_handles_ - handles_skipped; + + // Make the timeout be zero so that we don't block on any + // subsequent calls to WaitForMultipleObjects. Rather, we + // just poll through the rest looking for signaled handles. + timeout = 0; + } + } + } + + // Compute the time while the ReactorEx was processing. Note that + // this is recomputed to reflect time spent dispatching handlers. + ACE_Time_Value elapsed_time = ACE_OS::gettimeofday () - prev_time; + + // Update how_long to reflect the amount of time since handle_events + // was called. + if (how_long != 0) + { + if (*how_long > elapsed_time) + *how_long = *how_long - elapsed_time; + else + *how_long = ACE_Time_Value::zero; // Used all of timeout. + } + + return 0; +} + +// ************************************************************ + +void +ACE_ReactorEx_Token::dump (void) const +{ + ACE_TRACE ("ACE_ReactorEx_Token::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ReactorEx_Token::ACE_ReactorEx_Token (ACE_ReactorEx &r) + : reactorEx_ (r) +#if defined (ACE_ReactorEx_HAS_DEADLOCK_DETECTION) + , ACE_Local_Mutex (0) // Triggers unique name by stringifying "this"... +#endif /* ACE_ReactorEx_HAS_DEADLOCK_DETECTION */ +{ + ACE_TRACE ("ACE_ReactorEx_Token::ACE_ReactorEx_Token"); +} + +// Used to wakeup the Reactor. + +void +ACE_ReactorEx_Token::sleep_hook (void) +{ + ACE_TRACE ("ACE_ReactorEx_Token::sleep_hook"); + if (this->reactorEx_.notify () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "sleep_hook failed")); +} + +// ************************************************************ + +ACE_ReactorEx_Notify::ACE_ReactorEx_Notify (void) +{ + // Create an "auto-reset" event that is used to unblock the + // ReactorEx. + handle_ = ::CreateEvent (NULL, FALSE, FALSE, NULL); +} + +ACE_ReactorEx_Notify::~ACE_ReactorEx_Notify (void) +{ + ACE_OS::close (handle_); +} + +ACE_HANDLE +ACE_ReactorEx_Notify::get_handle (void) const +{ + return this->handle_; +} + +int +ACE_ReactorEx_Notify::handle_signal (int signum, siginfo_t *, ucontext_t *) +{ + // Do nothing. + return 0; +} + +int +ACE_ReactorEx_Notify::notify (void) +{ + return ::SetEvent (handle_) ? 0 : -1; +} + +#endif /* ACE_WIN32 */ diff --git a/ace/ReactorEx.h b/ace/ReactorEx.h new file mode 100644 index 00000000000..3b1bcc84a4b --- /dev/null +++ b/ace/ReactorEx.h @@ -0,0 +1,231 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ReactorEx.h +// +// = AUTHOR +// Tim Harrison and Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_ReactorEx_H) +#define ACE_ReactorEx_H + +#include "ace/Timer_Queue.h" +#include "ace/Time_Value.h" +#include "ace/Event_Handler.h" +#include "ace/Token.h" + +#if defined (ACE_MT_SAFE) + +#if defined (ACE_REACTOREX_HAS_DEADLOCK_DETECTION) +#include "ace/Local_Tokens.h" +typedef ACE_Local_Mutex ACE_REACTOREX_MUTEX; +#else +typedef ACE_Token ACE_REACTOREX_MUTEX; +#endif /* ACE_REACTOR_HAS_DEADLOCK_DETECTION */ + +// Forward decl. +class ACE_ReactorEx; + +class ACE_Export ACE_ReactorEx_Token : public ACE_REACTOREX_MUTEX +{ +public: + ACE_ReactorEx_Token (ACE_ReactorEx &r); + + virtual void sleep_hook (void); + // Called just before the ACE_Event_Handler goes to sleep. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_ReactorEx &reactorEx_; +}; + +#endif /* ACE_MT_SAFE */ + +#if defined (ACE_WIN32) +// ************************************************************ + +class ACE_Export ACE_ReactorEx_Notify : public ACE_Event_Handler +// = TITLE +// ReactorEx Notify +// +// = DESCRIPTION +// A "do-nothing" class that is called when ReactorEx::notify is +// called. +{ +public: + ACE_ReactorEx_Notify (void); + // Creates a handle. + + ~ACE_ReactorEx_Notify (void); + // Destroys a handle. + + int notify (void); + // Signals a handle. + +private: + virtual ACE_HANDLE get_handle (void) const; + // Returns a handle. + + virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0); + // Does nothing with a handle. + + ACE_HANDLE handle_; + // A handle. +}; + +class ACE_Export ACE_ReactorEx + // = TITLE + // An object oriented event demultiplexor and event handler + // ReactorEx for Win32 WaitForMultipleObjects + // + // = DESCRIPTION + + // The ACE_ReactorEx is an object-oriented event demultiplexor + // and event handler ReactorEx. The sources of events that the + // ACE_ReactorEx waits for and dispatches includes I/O events, + // general Win32 synchronization events (such as mutexes, + // semaphores, threads, etc.) and timer events. +{ +public: + enum + { + MAX_SIZE = MAXIMUM_WAIT_OBJECTS, + // Default size of the ReactorEx's handle table. + }; + + // = Initialization and termination methods. + + ACE_ReactorEx (void); + // Initialize the new ACE_ReactorEx with the default size. + + virtual ~ACE_ReactorEx (void); + // Close down the ReactorEx and release all of its resources. + + // = Event loop drivers. + // Main event loop driver that blocks for -how_long- before + // returning (will return earlier if I/O or signal events occur). + // Note that -how_long- can be 0, in which case this method blocks + // until I/O events or signals occur. Returns 0 if timed out, 1 if + // an event occurred, and -1 if an error occured. + virtual int handle_events (ACE_Time_Value *how_long = 0, + int wait_all = 0); + virtual int handle_events (ACE_Time_Value &how_long, + int wait_all = 0); + + + // = Register and remove Handlers. + virtual int register_handler (ACE_Event_Handler *eh, + ACE_HANDLE handle = ACE_INVALID_HANDLE); + // Register an Event_Handler -eh-. If handle == ACE_INVALID_HANDLE + // the ReactorEx will call eh->get_handle() to extract the + // underlying I/O handle). + + virtual int remove_handler (ACE_Event_Handler *eh, + ACE_Reactor_Mask mask = 0); + // Removes -eh- from the ReactorEx. Note that the ReactorEx will + // call eh->get_handle() to extract the underlying I/O handle. If + // -mask- == ACE_Event_Handler::DONT_CALL then the -handle_close- + // method of the -eh- is not invoked. + + virtual int notify (void); + // Wakeup ACE_ReactorEx if currently blocked + // WaitForMultipleObjects. + + // = Timer management. + virtual int schedule_timer (ACE_Event_Handler *eh, + const void *arg, + const ACE_Time_Value &delta, + const ACE_Time_Value &interval = ACE_Time_Value::zero); + // Schedule an Event Handler -eh- that will expire after -delta- + // amount of time. If it expires then -arg- is passed in as the + // value to eh->handle_timeout. If -interval- is != to + // ACE_Time_Value::zero then it is used to reschedule -eh- + // automatically. This method returns a timer handle that uniquely + // identifies the -eh- in an internal list. This timer handle can + // be used to cancel an Event_Handler before it expires. The + // cancellation ensures that timer_ids are unique up to values of + // greater than 2 billion timers. As long as timers don't stay + // around longer than this there should be no problems with + // accidentally deleting the wrong timer. + + virtual int cancel_timer (ACE_Event_Handler *event_handler); + // Cancel all Event_Handlers that match the address of + // -event_handler-. + + virtual int cancel_timer (int timer_id, const void **arg = 0); + // Cancel the single Event_Handler that matches the -timer_id- value + // (which was returned from the schedule method). If arg is + // non-NULL then it will be set to point to the ``magic cookie'' + // argument passed in when the Event_Handler was registered. This + // makes it possible to free up the memory and avoid memory leaks. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + int handle_notification (void); + // Handle the case where some thread has awakened us via our + // notification event. + + ACE_Timer_Queue timer_queue_; + // Defined as a pointer to allow overriding by derived classes... + + ACE_Time_Value timer_skew_; + // Adjusts for timer skew in various clocks. + + ACE_HANDLE handles_[MAX_SIZE]; + // Array of handles passed to WaitForMultipleObjects. + + ACE_Event_Handler *handlers_[MAX_SIZE]; + // Array of Event_Handler pointers that store the handlers to + // dispatch when the corresponding handles_ entry becomes signaled. + + size_t active_handles_; + // Number of handles that are currently active (ranges between 0 and + // MAX_SIZE). + + ACE_ReactorEx_Token token_; + // Synchronization token for the MT_SAFE ACE_Reactor. + +private: + + // Deny access since member-wise won't work... + ACE_ReactorEx (const ACE_ReactorEx &); + ACE_ReactorEx &operator = (const ACE_ReactorEx &); + + ACE_ReactorEx_Notify notify_handler_; + // Called when notify is called. +}; + +#else /* NOT win32 */ +class ACE_Export ACE_ReactorEx +{ +public: + virtual int handle_events (void) { return -1; } + virtual int handle_events (ACE_Time_Value &) { return -1; } + virtual int notify (void) { return 0; } +}; + +#endif /* ACE_WIN32 */ + +#if defined (__ACE_INLINE__) +#include "ace/ReactorEx.i" +#endif /* __ACE_INLINE__ */ +#endif /* ACE_ReactorEx_H */ diff --git a/ace/ReactorEx.i b/ace/ReactorEx.i new file mode 100644 index 00000000000..8ee3423cd22 --- /dev/null +++ b/ace/ReactorEx.i @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +#if defined (ACE_WIN32) + +ACE_INLINE int +ACE_ReactorEx::cancel_timer (ACE_Event_Handler *handler) +{ + ACE_TRACE ("ACE_ReactorEx::cancel_timer"); + return this->timer_queue_.cancel (handler); +} + +ACE_INLINE int +ACE_ReactorEx::cancel_timer (int timer_id, + const void **arg) +{ + ACE_TRACE ("ACE_ReactorEx::cancel_timer"); + return this->timer_queue_.cancel (timer_id, arg); +} + +ACE_INLINE int +ACE_ReactorEx::handle_events (ACE_Time_Value &how_long, + int wait_all) +{ + return this->handle_events (&how_long, wait_all); +} + +#endif /* ACE_WIN32 */ diff --git a/ace/Read_Buffer.cpp b/ace/Read_Buffer.cpp new file mode 100644 index 00000000000..9f49b7c7405 --- /dev/null +++ b/ace/Read_Buffer.cpp @@ -0,0 +1,155 @@ +// Read_Buffer.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Read_Buffer.h" +#include "ace/Service_Config.h" + +void +ACE_Read_Buffer::dump (void) const +{ + ACE_TRACE ("ACE_Read_Buffer::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "size_ = %d", this->size_)); + ACE_DEBUG ((LM_DEBUG, "\noccurrences_ = %d", this->occurrences_)); + ACE_DEBUG ((LM_DEBUG, "\nstream_ = %x", this->stream_)); + ACE_DEBUG ((LM_DEBUG, "\nallocator_ = %x", this->allocator_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Read_Buffer::ACE_Read_Buffer (FILE *fp, + int close_on_delete, + ACE_Allocator *allocator) + : stream_ (fp), + close_on_delete_ (close_on_delete), + allocator_ (allocator) +{ + ACE_TRACE ("ACE_Read_Buffer::ACE_Read_Buffer"); + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); +} + +ACE_Read_Buffer::ACE_Read_Buffer (int handle, + int close_on_delete, + ACE_Allocator *allocator) + : stream_ (::fdopen (handle, "r")), + close_on_delete_ (close_on_delete), + allocator_ (allocator) +{ + ACE_TRACE ("ACE_Read_Buffer::ACE_Read_Buffer"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); +} + +ACE_Read_Buffer::~ACE_Read_Buffer (void) +{ + ACE_TRACE ("ACE_Read_Buffer::~ACE_Read_Buffer"); + + if (this->close_on_delete_) + ::fclose (this->stream_); +} + +// Input: term the character to terminate on +// search the character to search for +// replace the character with which to replace search +// Output: a buffer containing the contents of stream +// Method: call the recursive helper function read_helper + +char * +ACE_Read_Buffer::read (int term, int search, int replace) +{ + ACE_TRACE ("ACE_Read_Buffer::read"); + this->occurrences_ = 0; + this->size_ = 0; + return this->rec_read (term, search, replace); +} + +// Input: term the termination character +// search the character to search for +// replace the character with which to replace search +// Purpose: read in a file to a buffer using only a single dynamic +// allocation. +// Method: read until the local buffer is full and then recurse. +// Must continue until the termination character is reached. +// Allocate the final buffer based on the number of local +// buffers read and as the recursive calls bottom out, +// copy them in reverse order into the allocated buffer. + +char * +ACE_Read_Buffer::rec_read (int term, int search, int replace) +{ + ACE_TRACE ("ACE_Read_Buffer::rec_read"); + // This is our temporary workspace. + char buf[BUFSIZ]; + + int c; + size_t index = 0; + int done = 0; + + // Read in the file char by char + while (index < BUFSIZ) + { + c = getc (this->stream_); + + // Don't insert EOF into the buffer... + if (c == EOF) + { + if (index == 0) + return 0; + else + { + ungetc (c, this->stream_); + break; + } + } + else if (c == term) + done = 1; + + // Check for possible substitutions. + if (c == search) + { + this->occurrences_++; + + if (replace >= 0) + c = replace; + } + + buf[index++] = c; + + // Substitutions must be made before checking for termination. + if (done) + break; + } + + // Increment the number of bytes. + this->size_ += index; + + char *result; + + // Recurse, when the recursion bottoms out, allocate the result + // buffer. + if (done || c == EOF) + { + // Use the allocator to acquire the memory. + result = (char *) this->allocator_->malloc (this->size_ * sizeof (char)); + + if (result == 0) + { + errno = ENOMEM; + return 0; + } + result += this->size_; + } + else if ((result = this->rec_read (term, search, replace)) == 0) + return 0; + + // Copy buf into the appropriate location starting from end of + // buffer. Peter says this is confusing and that we should use + // memcpy() ;-) + + for (size_t j = index; j > 0; j--) + *--result = buf[j - 1]; + + return result; +} diff --git a/ace/Read_Buffer.h b/ace/Read_Buffer.h new file mode 100644 index 00000000000..ff932925b60 --- /dev/null +++ b/ace/Read_Buffer.h @@ -0,0 +1,93 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Read_Buffer.h +// +// = AUTHOR +// Doug Schmidt and Seth Widoff +// +// ============================================================================ + +#if !defined (ACE_READ_BUFFER_H) +#define ACE_READ_BUFFER_H + +#include "ace/ACE.h" +#include "ace/Malloc.h" + +class ACE_Export ACE_Read_Buffer + // = TITLE + // Efficiently reads an artibrarily large buffer from an input + // stream up to an including a termination character. Also + // performs search/replace on single occurrences a character in + // the buffer using the priniciples of Integrated Layer + // Processing. + // + // = DESCRIPTION + // This implementation is optimized to do a single dynamic + // allocation and make only one copy of the data. It uses + // recursion and the run-time stack to accomplish this + // efficiently. +{ +public: + // = Initialization and termination methods. + ACE_Read_Buffer (FILE *fp, int close_on_delete = 0, ACE_Allocator * = 0); + // Read from a FILE *. + + ACE_Read_Buffer (int handle, int close_on_delete = 0, ACE_Allocator * = 0); + // Read from an open HANDLE. + + ~ACE_Read_Buffer (void); + // Closes the FILE *. + + // Returns a dynamically allocated pointer to n bytes of data from + // the input stream up to (and including) the <terminator>. If + // <search> is >= 0 then all occurrences of the <search> value are + // substituted with the <replace> value. + char *read (int terminator = EOF, + int search = '\n', + int replace = '\0'); + + size_t replaced (void) const; + // Returns the number of characters replaced during a <read>. + + size_t size (void) const; + // Returns the size of the allocated buffer obtained during a <read>. + + void dump (void) const; + // Dump the state of the object. + +private: + char *rec_read (int term, int search, int replace); + // Recursive helper method that does the work... + + size_t size_; + // The total number of characters in the buffer. + + size_t occurrences_; + // The total number of characters replaced. + + FILE *stream_; + // The stream we are reading from. + + int close_on_delete_; + // Keeps track of whether we should close the FILE in the + // destructor. + + ACE_Allocator *allocator_; + // Pointer to the allocator. + + // = Disallow copying and assignment... + void operator= (const ACE_Read_Buffer &); + ACE_Read_Buffer (const ACE_Read_Buffer &); +}; + +#include "ace/Read_Buffer.i" + +#endif /* ACE_READ_BUFFER_H */ diff --git a/ace/Read_Buffer.i b/ace/Read_Buffer.i new file mode 100644 index 00000000000..fc8be70166c --- /dev/null +++ b/ace/Read_Buffer.i @@ -0,0 +1,23 @@ +/* -*- C++ -*- */ +// $Id$ + +// Read_Buffer.i + +// Accessor to the number of bytes in the buffer. + +inline size_t +ACE_Read_Buffer::size (void) const +{ + ACE_TRACE ("ACE_Read_Buffer::size"); + return this->size_; +} + +// The total number of characters replaced. + +inline size_t +ACE_Read_Buffer::replaced (void) const +{ + ACE_TRACE ("ACE_Read_Buffer::replaced"); + return this->occurrences_; +} + diff --git a/ace/Remote_Name_Space.cpp b/ace/Remote_Name_Space.cpp new file mode 100644 index 00000000000..9125b4e47a7 --- /dev/null +++ b/ace/Remote_Name_Space.cpp @@ -0,0 +1,312 @@ +// Remote_Name_Space.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Remote_Name_Space.h" + +int +ACE_Remote_Name_Space::open (const char *servername, int port) +{ + ACE_TRACE ("ACE_Remote_Name_Space::open"); + ACE_INET_Addr servaddr; + + // Initialize Addr + if (servaddr.set (port, servername) == -1) + return -1; + + // Connect to Name Server process. + if (this->ns_proxy_.open (servaddr) == -1) + return -1; + + return 0; +} + +ACE_Remote_Name_Space::ACE_Remote_Name_Space (void) +{ + ACE_TRACE ("ACE_Remote_Name_Space::ACE_Remote_Name_Space"); +} + +ACE_Remote_Name_Space::ACE_Remote_Name_Space (const char *hostname, int port) +{ + ACE_TRACE ("ACE_Remote_Name_Space::ACE_Remote_Name_Space"); + if (this->open (hostname, port) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::ACE_Remote_Name_Space")); +} + +int +ACE_Remote_Name_Space::bind (const ACE_WString &name, + const ACE_WString &value, + const char *type) +{ + ACE_TRACE ("ACE_Remote_Name_Space::bind"); + ACE_Name_Request request (ACE_Name_Request::BIND, name.rep (), + name.length () * sizeof (ACE_USHORT16), + value.rep (), + value.length () * sizeof (ACE_USHORT16), + type, strlen (type)); + int result = this->ns_proxy_.request_reply (request); + return result == ACE_Name_Reply::SUCCESS ? 0 : result; +} + +int +ACE_Remote_Name_Space::rebind (const ACE_WString &name, + const ACE_WString &value, + const char *type) +{ + ACE_TRACE ("ACE_Remote_Name_Space::rebind"); + ACE_Name_Request request (ACE_Name_Request::REBIND, name.rep (), + name.length () * sizeof (ACE_USHORT16), + value.rep (), + value.length () * sizeof (ACE_USHORT16), + type, strlen (type)); + int result = this->ns_proxy_.request_reply (request); + return result == ACE_Name_Reply::SUCCESS ? 0 : result; +} + +int +ACE_Remote_Name_Space::resolve (const ACE_WString &name, + ACE_WString &value, + char *&type) +{ + ACE_TRACE ("ACE_Remote_Name_Space::resolve"); + ACE_Name_Request request (ACE_Name_Request::RESOLVE, name.rep (), + name.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply; + + if (this->ns_proxy_.recv_reply (reply) == -1) + return -1; + + ACE_WString temp (reply.value (), reply.value_len () / sizeof (ACE_USHORT16)); + value = temp; + ACE_NEW_RETURN (type, char[reply.type_len ()], -1); + ACE_OS::strcpy (type, reply.type ()); + + return 0; +} + +int +ACE_Remote_Name_Space::unbind (const ACE_WString &name) +{ + ACE_TRACE ("ACE_Remote_Name_Space::unbind"); + ACE_Name_Request request (ACE_Name_Request::UNBIND, name.rep (), + name.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + int result = this->ns_proxy_.request_reply (request); + return result == ACE_Name_Reply::SUCCESS ? 0 : result; +} + +int +ACE_Remote_Name_Space::list_names (ACE_WSTRING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Remote_Name_Space::list_names"); + ACE_Name_Request request (ACE_Name_Request::LIST_NAMES, pattern.rep (), + pattern.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply (0, NULL, 0, NULL, 0, NULL, 0, 0); + + while (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + if (this->ns_proxy_.recv_reply (reply) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::list_names")); + return -1; + } + if (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + ACE_WString name (reply.name (), reply.name_len () / sizeof (ACE_USHORT16)); + set.insert (name); + } + } + return 0; +} + +int +ACE_Remote_Name_Space::list_values (ACE_WSTRING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Remote_Name_Space::list_values"); + ACE_Name_Request request (ACE_Name_Request::LIST_VALUES, pattern.rep (), + pattern.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply (0, NULL, 0, NULL, 0, NULL, 0, 0); + + while (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + if (this->ns_proxy_.recv_reply (reply) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::list_values")); + return -1; + } + if (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + ACE_WString value (reply.value (), reply.value_len () / sizeof (ACE_USHORT16)); + set.insert (value); + } + } + return 0; +} + +int +ACE_Remote_Name_Space::list_types (ACE_WSTRING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Remote_Name_Space::list_types"); + ACE_Name_Request request (ACE_Name_Request::LIST_TYPES, pattern.rep (), + pattern.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply (0, NULL, 0, NULL, 0, NULL, 0, 0); + + while (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + if (this->ns_proxy_.recv_reply (reply) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::list_values")); + return -1; + } + if (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + ACE_WString type (reply.type ()); + set.insert (type); + } + } + return 0; +} + +int +ACE_Remote_Name_Space::list_name_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Remote_Name_Space::list_names"); + ACE_Name_Request request (ACE_Name_Request::LIST_NAME_ENTRIES, pattern.rep (), + pattern.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply (0, NULL, 0, NULL, 0, NULL, 0, 0); + + while (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + if (this->ns_proxy_.recv_reply (reply) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::list_names")); + return -1; + } + if (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + ACE_WString name (reply.name (), reply.name_len () / sizeof (ACE_USHORT16)); + ACE_WString value (reply.value (), reply.value_len () / sizeof (ACE_USHORT16)); + ACE_Name_Binding entry (name, value, reply.type ()); + + if (set.insert (entry) == -1) + return -1; + } + } + return 0; +} + +int +ACE_Remote_Name_Space::list_value_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Remote_Name_Space::list_values"); + ACE_Name_Request request (ACE_Name_Request::LIST_VALUE_ENTRIES, pattern.rep (), + pattern.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply (0, NULL, 0, NULL, 0, NULL, 0, 0); + + while (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + if (this->ns_proxy_.recv_reply (reply) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::list_values")); + return -1; + } + if (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + ACE_WString name (reply.name (), reply.name_len () / sizeof (ACE_USHORT16)); + ACE_WString value (reply.value (), reply.value_len () / sizeof (ACE_USHORT16)); + ACE_Name_Binding entry (name, value, reply.type()); + + if (set.insert (entry) == -1) + return -1; + } + } + return 0; +} + +int +ACE_Remote_Name_Space::list_type_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern) +{ + ACE_TRACE ("ACE_Remote_Name_Space::list_types"); + ACE_Name_Request request (ACE_Name_Request::LIST_TYPE_ENTRIES, pattern.rep (), + pattern.length () * sizeof (ACE_USHORT16), + NULL, 0, NULL, 0); + + if (this->ns_proxy_.send_request (request) == -1) + return -1; + + ACE_Name_Request reply (0, NULL, 0, NULL, 0, NULL, 0, 0); + + while (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + if (this->ns_proxy_.recv_reply (reply) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Remote_Name_Space::list_values")); + return -1; + } + if (reply.msg_type () != ACE_Name_Request::MAX_ENUM) + { + ACE_WString name (reply.name (), reply.name_len () / sizeof (ACE_USHORT16)); + ACE_WString value (reply.value (), reply.value_len () / sizeof (ACE_USHORT16)); + ACE_Name_Binding entry (name, value, reply.type()); + + if (set.insert (entry) == -1) + return -1; + } + } + return 0; +} + + +ACE_Remote_Name_Space::~ACE_Remote_Name_Space (void) +{ + ACE_TRACE ("ACE_Remote_Name_Space::~ACE_Remote_Name_Space"); +} + +void +ACE_Remote_Name_Space::dump (void) const +{ + ACE_TRACE ("ACE_Remote_Name_Space::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->ns_proxy_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + diff --git a/ace/Remote_Name_Space.h b/ace/Remote_Name_Space.h new file mode 100644 index 00000000000..a81c15b6bbb --- /dev/null +++ b/ace/Remote_Name_Space.h @@ -0,0 +1,126 @@ +/* -*- C++ -*- */ +// $Id$ + +/*-*- C++ -*- */ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Remote_Name_Space +// +// = AUTHOR +// Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_REMOTE_NAME_SPACE_H) +#define ACE_REMOTE_NAME_SPACE_H + +#include "ace/ACE.h" +#include "ace/SString.h" +#include "ace/Set.h" +#include "ace/Name_Proxy.h" +#include "ace/Name_Space.h" + +typedef ACE_Unbounded_Set<ACE_WString> ACE_WSTRING_SET; + +class ACE_Export ACE_Remote_Name_Space : public ACE_Name_Space + // = TITLE + // Maintaining accesses Remote Name Server Database. Allows to + // add NameBindings, change them, remove them and resolve + // NameBindings. + // + // = DESCRIPTION + // Manages a Naming Service for a remote name space which includes + // bindings for net_local naming context. + // All strings are stored in wide character format. + // A Name Binding consists of a name (that's the key), a value + // string and an optional type string (no wide chars). +{ +public: + // = Initialization and termination methods. + ACE_Remote_Name_Space (void); + // "Do-nothing" constructor. + + ACE_Remote_Name_Space (const char *hostname, int port); + // Specifies the scope of this namespace, opens and memory-maps the + // associated file (if accessible) or contacts the dedicated name + // server process for NET_LOCAL namespace. + + int open (const char *servername, int port); + // Specifies the scope of this namespace, opens and memory-maps the + // associated file (if accessible) or contacts the dedicated name + // server process for NET_LOCAL namespace. + + ~ACE_Remote_Name_Space (void); + // destructor, do some cleanup :TBD: last dtor should "compress" + // file + + virtual int bind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in = ""); + // Bind a new name to a naming context (Wide character strings). + + virtual int rebind (const ACE_WString &name_in, + const ACE_WString &value_in, + const char *type_in = ""); + // Overwrite the value or type of an existing name in a + // ACE_Remote_Name_Space or bind a new name to the context, if it + // didn't exist yet. (Wide charcter strings interface). + + virtual int unbind (const ACE_WString &name_in); + // Delete a name from a ACE_Remote_Name_Space (Wide charcter strings + // Interface). + + virtual int resolve (const ACE_WString &name_in, + ACE_WString &value_out, + char *&type_out); + // Get value and type of a given name binding (Wide chars). The + // caller is responsible for deleting both <value_out> and <type_out>! + + virtual int list_names (ACE_WSTRING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. + + virtual int list_values (ACE_WSTRING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. + + virtual int list_types (ACE_WSTRING_SET &set_out, + const ACE_WString &pattern_in); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. + + virtual int list_name_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern); + // Get a set of names matching a specified pattern (wchars). Matching + // means the names must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_value_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern); + // Get a set of values matching a specified pattern (wchars). Matching + // means the values must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual int list_type_entries (ACE_BINDING_SET &set, + const ACE_WString &pattern); + // Get a set of types matching a specified pattern (wchars). Matching + // means the types must begin with the pattern string. Returns the + // complete binding associated each pattern match. + + virtual void dump (void) const; + // Dump the state of the object. + +private: + + ACE_Name_Proxy ns_proxy_; + // Interface to Name server process for NET_LOCAL namespace. +}; + +#endif /* ACE_REMOTE_NAME_SPACE_H */ diff --git a/ace/Remote_Tokens.cpp b/ace/Remote_Tokens.cpp new file mode 100644 index 00000000000..e07b91a70ca --- /dev/null +++ b/ace/Remote_Tokens.cpp @@ -0,0 +1,445 @@ +// Remote_Tokens.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Remote_Tokens.h" +#include "ace/Singleton.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Remote_Tokens.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_MT_SAFE) +typedef ACE_Thread_Mutex ACE_TSS_CONNECTION_MUTEX; +#else +typedef ACE_Null_Mutex ACE_TSS_CONNECTION_MUTEX; +#endif /* ACE_MT_SAFE */ + +// Make a typedef to simplify access to the Singleton below. +typedef ACE_Singleton<ACE_TSS_Connection, ACE_TSS_CONNECTION_MUTEX> + ACE_Token_Connections; + +// Initialize the statics from ACE_TSS_Connection; +ACE_INET_Addr ACE_TSS_Connection::server_address_; + +// ************************************************************ + +void +ACE_TSS_Connection::set_server_address (const ACE_INET_Addr &server_address) +{ + ACE_TRACE ("ACE_TSS_Connection::set_server_address"); + server_address_ = server_address; +} + +// Necessary to make some compilers work... +ACE_TSS_Connection::ACE_TSS_Connection (void) +{ + ACE_TRACE ("ACE_TSS_Connection::ACE_TSS_Connection"); +} + +ACE_TSS_Connection::~ACE_TSS_Connection (void) +{ + ACE_TRACE ("ACE_TSS_Connection::~ACE_TSS_Connection"); +} + +ACE_SOCK_Stream * +ACE_TSS_Connection::get_connection (void) +{ + return ACE_TSS<ACE_SOCK_Stream>::operator-> (); +} + +ACE_SOCK_Stream * +ACE_TSS_Connection::make_TSS_TYPE (void) const +{ + ACE_TRACE ("ACE_TSS_Connection::make_TSS_TYPE"); + + ACE_SOCK_Connector connector; + ACE_SOCK_Stream *stream = 0; + + ACE_NEW_RETURN (stream, ACE_SOCK_Stream, 0); + + if (connector.connect (*stream, server_address_) == -1) + { + delete stream; + errno = ECONNREFUSED; + return 0; + } + + ACE_DEBUG ((LM_DEBUG, "ACE_TSS_Connection new connection\n")); + return stream; +} + +ACE_TSS_Connection::operator ACE_SOCK_Stream *(void) +{ + return this->get_connection (); +} + + +void +ACE_TSS_Connection::dump (void) const +{ + ACE_TRACE ("ACE_TSS_Connection::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_TSS_Connection::dump:\n")); + ACE_DEBUG ((LM_DEBUG, "server_address_\n")); + server_address_.dump (); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_TSS<ACE_SOCK_Stream>::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +ACE_Remote_Token_Proxy::ACE_Remote_Token_Proxy (void) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::ACE_Remote_Token_Proxy"); +} + +ACE_Remote_Token_Proxy::~ACE_Remote_Token_Proxy (void) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::~ACE_Remote_Token_Proxy"); +} + +int +ACE_Remote_Token_Proxy::open (const char *name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::open"); + ignore_shadow_deadlock_ = ignore_deadlock; + return ACE_Token_Proxy::open (name, 0, debug); +} + +void +ACE_Remote_Token_Proxy::set_server_address (const ACE_INET_Addr &server_address) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::set_server_address"); + ACE_Token_Connections::instance ()->set_server_address (server_address); +} + +int +ACE_Remote_Token_Proxy::initiate_connection (void) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::initiate_connection"); + if (token_ == 0) + { + errno = ENOENT; + ACE_ERROR_RETURN ((LM_ERROR, "ACE_Remote_Token_Proxy not open.\n"), -1); + } + + ACE_SOCK_Stream *peer = ACE_Token_Connections::instance ()->get_connection (); + return peer == 0 ? 0 : 1; +} + +// Do the work of sending a request and getting a reply. + +int +ACE_Remote_Token_Proxy::request_reply (ACE_Token_Request &request, + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::request_reply"); + void *buffer; + ssize_t length; + +// request.dump (); + + if ((length = request.encode (buffer)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "encode failed"), -1); + + ACE_SOCK_Stream *peer = ACE_Token_Connections::instance ()->get_connection (); + + if (peer == 0) + return -1; + + // Transmit request via a blocking send. + + if (peer->send_n (buffer, length) != length) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send_n failed"), -1); + else + { + ACE_Token_Reply reply; + + // Receive reply via blocking read. + + if (peer->recv (&reply, sizeof reply) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "recv failed"), -1); + + if (reply.decode () == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "decode failed"), -1); + + errno = int (reply.errnum ()); + if (errno != 0) + ACE_RETURN (-1); + else + return 0; + } +} + +int +ACE_Remote_Token_Proxy::acquire (int notify, + void (*sleep_hook)(void *), + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::acquire"); + + // First grab the local shadow mutex. + if (ACE_Token_Proxy::acquire (notify, + sleep_hook, + ACE_Synch_Options::asynch) == -1) + { + // Acquire failed, deal with it... + switch (errno) + { + case EWOULDBLOCK : + // Whoah, we detected wouldblock via the shadow mutex! + if (debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) shadow: acquire will block, owner is %s\n", + this->token_->owner_id ())); + // No error, but would block, + break; + + case EDEADLK : + if (debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) shadow: deadlock detected\n")); + + if (ignore_shadow_deadlock_) + break; + else + { + errno = EDEADLK; + ACE_RETURN (-1); + } + + default : + ACE_ERROR_RETURN ((LM_ERROR, + "(%t) %p shadow acquire failed\n", + "ACE_Remote_Token_Proxy"), + -1); + } + } + + ACE_Token_Request request (token_->type (), + this->type (), + ACE_Token_Request::ACQUIRE, + this->name (), + this->client_id (), + options); + + request.notify (notify); + + int result = this->request_reply (request, options); + + if (result == -1) + { + // Update the local shadow copy. + ACE_DEBUG ((LM_DEBUG, "error on remote acquire, releasing shadow mutex.\n")); + ACE_Token_Proxy::release (); + } + else + { + ACE_DEBUG ((LM_DEBUG, "(%t) acquired %s remotely.\n", this->name ())); + // Our shadow call may have failed. However, it's still a race + // to the remote server. If we beat the client which holds the + // local token, we need to fix things locally to reflect the + // actual ownership. All that should happen is that our waiter + // is moved to the front of the waiter list. + token_->make_owner (waiter_); + } + + return result; +} + +int +ACE_Remote_Token_Proxy::tryacquire (void (*sleep_hook)(void *)) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::tryacquire"); + + // If we can detect locally that the tryacquire will fail, there is + // no need to go remote. + if (ACE_Token_Proxy::tryacquire (sleep_hook) == -1) + { + if (debug_) + { + int error = errno; + ACE_DEBUG ((LM_DEBUG, "shadow try acquire failed\n")); + errno = error; + } + + return -1; + } + + ACE_Token_Request request (token_->type (), + this->type (), + ACE_Token_Request::RELEASE, + this->name (), + this->client_id (), + ACE_Synch_Options::synch); + + return this->request_reply (request, + ACE_Synch_Options::synch); +} + +int +ACE_Remote_Token_Proxy::renew (int requeue_position, + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::renew"); + + if (ACE_Token_Proxy::renew (requeue_position, + ACE_Synch_Options::asynch) == -1) + { + // Check for error. + if (errno != EWOULDBLOCK) + return -1; + else if (debug_) + ACE_DEBUG ((LM_DEBUG, + "(%t) shadow: renew would block. owner %s.\n", + this->token_->owner_id ())); + } + + ACE_Token_Request request (token_->type (), + this->type (), + ACE_Token_Request::RENEW, + this->name (), + this->client_id (), + options); + + request.requeue_position (requeue_position); + + int result = this->request_reply (request, options); + + if (result == -1) + { + int error = errno; + ACE_Token_Proxy::release (); + errno = error; + ACE_ERROR_RETURN ((LM_ERROR, "%p error on remote renew, releasing shadow mutex.\n", + "ACE_Remote_Token_Proxy"), -1); + } + else + { + if (debug_) + ACE_DEBUG ((LM_DEBUG, "(%t) renewed %s remotely.\n", this->name ())); + // Make sure that the local shadow reflects our new ownership. + token_->make_owner (waiter_); + return result; + } +} + +int +ACE_Remote_Token_Proxy::release (ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::release"); + + ACE_Token_Request request (token_->type (), + this->type (), + ACE_Token_Request::RELEASE, + this->name (), + this->client_id (), + options); + + int result = this->request_reply (request, options); + if (result == 0) + ACE_DEBUG ((LM_DEBUG, "(%t) released %s remotely.\n", this->name ())); + + // whether success or failure, we're going to release the shadow. + // If race conditions exist such that we are no longer the owner, + // this release will perform a remove. + if (ACE_Token_Proxy::release () == -1) + ACE_ERROR ((LM_ERROR, "(%t) shadow: release failed\n")); + + return result; +} + +int +ACE_Remote_Token_Proxy::remove (ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::remove"); + return 0; +} + +void +ACE_Remote_Token_Proxy::token_acquired (ACE_TPQ_Entry *e) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::token_acquired"); + ACE_DEBUG ((LM_DEBUG, "(%t) shadow token %s acquired\n", + this->client_id (), + this->name ())); + // ACE_Token_Proxy::token_acquired (vp); +} + +const char* +ACE_Remote_Token_Proxy::owner_id (void) +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::owner_id"); + ACE_DEBUG ((LM_DEBUG, "owner_id called\n")); + // @@ special operation + return 0; +} + +void +ACE_Remote_Token_Proxy::dump (void) const +{ + ACE_TRACE ("ACE_Remote_Token_Proxy::owner_id"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Tokens::dump:\n" + " ignore_shadow_deadlock_ = %d\n", + ignore_shadow_deadlock_)); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Token_Proxy::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_Remote_Mutex::dump (void) const +{ + ACE_TRACE ("ACE_Remote_Mutex::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Remote_Mutex::dump:\n")); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Remote_Token_Proxy::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_Remote_RLock::dump (void) const +{ + ACE_TRACE ("ACE_Remote_RLock::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Remote_RLock::dump:\n")); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Remote_Token_Proxy::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +void +ACE_Remote_WLock::dump (void) const +{ + ACE_TRACE ("ACE_Remote_WLock::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Remote_WLock::dump:\n")); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Remote_Token_Proxy::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_TSS <ACE_SOCK_Stream>; +template class ACE_Singleton <ACE_TSS_Connection, ACE_TSS_CONNECTION_MUTEX>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Remote_Tokens.h b/ace/Remote_Tokens.h new file mode 100644 index 00000000000..63217c54390 --- /dev/null +++ b/ace/Remote_Tokens.h @@ -0,0 +1,283 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// Remote_Tokens.h +// +// = AUTHOR +// Douglas C. Schmidt (schmidt@cs.wustl.edu) and +// Tim Harrison (harrison@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (ACE_REMOTE_MUTEX_H) +#define ACE_REMOTE_MUTEX_H + +#include "ace/INET_Addr.h" +#include "ace/SOCK_Connector.h" +#include "ace/SOCK_Stream.h" +#include "ace/Synch_Options.h" +#include "ace/Local_Tokens.h" +#include "ace/Token_Request_Reply.h" +#include "ace/Synch.h" + +class ACE_Export ACE_Remote_Token_Proxy : public ACE_Token_Proxy + // = TITLE + // Proxy for acquiring, renewing, and releasing a distributed + // synchronization token. + // + // = DESCRIPTION + // The Remote_Token_Proxy class implements the mechanisms for + // distributed token operations. It is similar to the + // ACE_Token_Proxy. + // + // = BUGS + // Distributed sleep_hooks have not been implemented. owner_id () + // is not implemented. +{ +public: + ACE_Remote_Token_Proxy (void); + // Null construction. + + virtual ~ACE_Remote_Token_Proxy (void); + // Death. + + int open (const char *name, + int ignore_deadlock = 0, + int debug = 0); + // Same as Token_Proxy. <name> is the string uniquely identifying + // the token. <ignore_deadlock> can be 1 to disable deadlock + // notifications. <debug> prints debug messages. + + + int initiate_connection (void); + // Open a connection with the token server. This only need be used + // when the user wishes to explicitly open a connection to check if + // the server exists. Connections are stored in the + // ACE_Token_Connections singleton as thread-specific data. That + // is, every thread has only one connection that is used for all + // remote tokens. + + virtual int acquire (int notify = 0, + void (*sleep_hook)(void *) = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::synch); + // Acquire the distributed token. If notify is specified and the + // token is already held, the owner is notified. options contains + // the timeout value for the acquire call. The timer is kept at the + // token server. Asynchronous operations are not supported. + // Returns 0 on success, -1 on failure with <errno> == problem. + + virtual int tryacquire (void (*sleep_hook)(void *) = 0); + // Try to acquire the distributed token. If the token is already + // held, the call returns without queueing the caller as a waiter. + // Returns 0 on success (the token was acquired), and -1 with + // EWOULDBLOCK if the token was already held. + + virtual int renew (int requeue_position = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::synch); + // Renew the token by offering to release it if there are any other + // waiters, otherwise get the token back immediately. This renew + // has the same semantics as ACE_Local_Mutex release. It is + // semantically equivalent to <this->release()> followed by + // <this->acquire()>, but it is faster. options contains the + // timeout value used if renew blocks. As with acquire, the timer + // is maintained at the token server. If there are waiters and + // requeue_position == -1, the caller is queued at the rear of the + // waiter list. Otherwise, requeue_position specifies the number of + // waiters to "let by" before reacquiring the token (effectively, + // the position in the waiter list.) + + virtual int release (ACE_Synch_Options &options = + ACE_Synch_Options::synch); + // Release the distributed token. Similar to ACE_Local_Mutex, if the + // caller is not the owner, it is removed from the waiter list (if + // applicable.) Returns 0 on success, -1 on failure with <errno> == + // problem. + + virtual int remove (ACE_Synch_Options &options = + ACE_Synch_Options::synch); + // Become interface compliant for ACE_Guard<>. This has no + // functionality. + + virtual void token_acquired (ACE_TPQ_Entry *); + // Override the default to do nothing. + + virtual const char* owner_id (void); + // the client id of the current token holder + + static void set_server_address (const ACE_INET_Addr &server_address); + // sets the server address for all instances of ACE_Remote_Token_Proxy + // If this isn't called, the environment variable TOKEN_SERVER is + // checked for the server address. If that is not specified, all + // ACE_Remote_** operations will fail. + + void dump (void) const; + // Dump the state of the class. + +protected: + + int ignore_shadow_deadlock_; + // if shadows report deadlock, go remote anyway + + int request_reply (ACE_Token_Request &request, + ACE_Synch_Options &options); + // Perform the request and wait for the reply. +}; + +class ACE_Export ACE_Remote_Mutex : public ACE_Remote_Token_Proxy +// = TITLE +// Proxy for acquiring, renewing, and releasing a distributed +// mutex. +// +// = DESCRIPTION +// This is the remote equivalent to ACE_Local_Mutex. The +// Remote_Mutex class offers methods for acquiring, renewing, and +// releasing a distributed synchronization mutex. Similar to +// ACE_Local_Mutex, ACE_Remote_Token_Proxy offers recursive +// acquisition, FIFO waiter ordering, and deadlock detection. It +// depends on the Token Server for its distributed synchronization +// semantics. +{ +public: + ACE_Remote_Mutex (void); + // Null creation. Remote_Token_Proxy::open must be called. + + ACE_Remote_Mutex (const char *token_name, + int ignore_deadlock = 0, + int debug = 0); + // Calls Remote_Token_Proxy::open for you. + + void dump (void) const; + // Dump the state of the class. + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Make the correct type of ACE_Tokens. This is called by the Token + // Manager. +}; + +class ACE_Export ACE_Remote_RLock : public ACE_Remote_Token_Proxy +// = TITLE +// Proxy for acquiring, renewing, and releasing a distributed +// readers lock. +// +// = DESCRIPTION +// This is the remote equivalent to ACE_Local_RLock. Multiple +// readers can hold the lock simultaneously when no writers have +// the lock. Alternatively, when a writer holds the lock, no other +// participants (readers or writers) may hold the lock. +// ACE_Remote_RLock depends on the ACE Token Server for its +// distributed synchronization semantics. +{ +public: + ACE_Remote_RLock (void); + + ACE_Remote_RLock (const char *token_name, + int ignore_deadlock = 0, + int debug = 0); + + ACE_Remote_RLock (const ACE_Remote_RLock &mutex); + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_RW_Token::RLOCK; + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Make the correct type of ACE_Tokens. This is called by the Token + // Manager. +}; + +class ACE_Export ACE_Remote_WLock : public ACE_Remote_Token_Proxy + // = TITLE + // Proxy for acquiring, renewing, and releasing a distributed + // writers lock. + // + // = DESCRIPTION + // Shields applications from details of interacting with the + // ACE_Token_Server. The token_name_ is just the string that the + // Token Server uses to identify the token. The client_id_ (also + // used by the Token Server,) identifies the owner of the token and + // is used for deadlock detection. +{ +public: + ACE_Remote_WLock (void); + + ACE_Remote_WLock (const char *token_name, + int ignore_deadlock = 0, + int debug = 0); + + ACE_Remote_WLock (const ACE_Remote_WLock &mutex); + + void dump (void) const; + // Dump the state of the class. + + virtual int type (void) const; + // Returns ACE_RW_Token::WLOCK; + + virtual ACE_Token_Proxy *clone (void) const; + // Return deep copy. + +protected: + virtual ACE_Tokens *create_token (const char *name); + // Make the correct type of ACE_Tokens. This is called by the Token + // Manager. +}; + +class ACE_Export ACE_TSS_Connection : public ACE_TSS<ACE_SOCK_Stream> + // = TITLE + // Class for providing a connection per thread. + // + // = DESCRIPTION + // ACE_TSS_Connection provides a single access point for all + // threads to access thread-specific connections. This prevents + // resource-sharing problems such as thread serialization. +{ +public: + // Necessary to make some compilers work... + ACE_TSS_Connection (void); + ~ACE_TSS_Connection (void); + + ACE_SOCK_Stream *get_connection (void); + // retrieve the thread's connection + + virtual ACE_SOCK_Stream *make_TSS_TYPE (void) const; + // Factory Method that creates a new SOCK Stream. + + operator ACE_SOCK_Stream *(void); + // inheritence and operator overloading don't mix. Redefine this + // from ACE_TSS so that we can use it. + + static void set_server_address (const ACE_INET_Addr &server_address); + // Set the server address. + + void dump (void) const; + // Dump the state of the class. + +protected: + static ACE_INET_Addr server_address_; + // The address of the Token Server used by all instances of + // Token_Proxy. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Remote_Tokens.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_REMOTE_TOKEN_H */ diff --git a/ace/Remote_Tokens.i b/ace/Remote_Tokens.i new file mode 100644 index 00000000000..2a87bf30919 --- /dev/null +++ b/ace/Remote_Tokens.i @@ -0,0 +1,98 @@ +/* -*- C++ -*- */ +// $Id$ + +// Remote_Tokens.i + +ACE_INLINE +ACE_Remote_Mutex::ACE_Remote_Mutex (void) +{ + ACE_TRACE ("ACE_Remote_Mutex::ACE_Remote_Mutex"); +} + +ACE_INLINE +ACE_Remote_Mutex::ACE_Remote_Mutex (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Remote_Mutex::ACE_Remote_Mutex"); + this->open (token_name, ignore_deadlock, debug); +} + +ACE_INLINE ACE_Token_Proxy * +ACE_Remote_Mutex::clone (void) const +{ + return new ACE_Remote_Mutex (this->name (), + ignore_deadlock_, + debug_); +} + +ACE_INLINE ACE_Tokens * +ACE_Remote_Mutex::create_token (const char *name) +{ + return new ACE_Mutex_Token (name); +} + +// ************************************************************ + +ACE_INLINE +ACE_Remote_RLock::ACE_Remote_RLock (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Remote_RLock::ACE_Remote_RLock"); + this->open (token_name, ignore_deadlock, debug); +} + +ACE_INLINE ACE_Tokens * +ACE_Remote_RLock::create_token (const char *name) +{ + return new ACE_RW_Token (name); +} + +ACE_INLINE int +ACE_Remote_RLock::type (void) const +{ + return ACE_RW_Token::READER; +} + +ACE_INLINE ACE_Token_Proxy * +ACE_Remote_RLock::clone (void) const +{ + return new ACE_Remote_RLock (this->name (), + ignore_deadlock_, + debug_); +} + +// ************************************************************ + +ACE_INLINE +ACE_Remote_WLock::ACE_Remote_WLock (const char *token_name, + int ignore_deadlock, + int debug) +{ + ACE_TRACE ("ACE_Remote_WLock::ACE_Remote_WLock"); + this->open (token_name, ignore_deadlock, debug); +} + + +ACE_INLINE ACE_Tokens * +ACE_Remote_WLock::create_token (const char *name) +{ + return new ACE_RW_Token (name); +} + +ACE_INLINE int +ACE_Remote_WLock::type (void) const +{ + return ACE_RW_Token::WRITER; +} + +ACE_INLINE ACE_Token_Proxy * +ACE_Remote_WLock::clone (void) const +{ + return new ACE_Remote_WLock (this->name (), + ignore_deadlock_, + debug_); +} + + diff --git a/ace/SOCK.cpp b/ace/SOCK.cpp new file mode 100644 index 00000000000..251e9e71eac --- /dev/null +++ b/ace/SOCK.cpp @@ -0,0 +1,97 @@ +// SOCK.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SOCK.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK) + +#if defined (ACE_WIN32) +// Static used to initialize WinSock. +ACE_SOCK ACE_SOCK::dummy_; +#endif /* ACE_WIN32 */ + +void +ACE_SOCK::dump (void) const +{ + ACE_TRACE ("ACE_SOCK::dump"); +} + +ACE_SOCK::ACE_SOCK (void) +{ + ACE_TRACE ("ACE_SOCK::ACE_SOCK"); + + // Make sure that we've initialized the WinSock library before using + // sockets! + ACE_OS::socket_init (ACE_WSOCK_VERSION); +} + +// Returns information about the remote peer endpoint (if there is +// one). + +int +ACE_SOCK::get_remote_addr (ACE_Addr &sa) const +{ + ACE_TRACE ("ACE_SOCK::get_remote_addr"); + int len = sa.get_size (); + sockaddr *addr = (sockaddr *) sa.get_addr (); + + if (ACE_OS::getpeername (this->get_handle (), addr, &len) == -1) + return -1; + + sa.set_size (len); + return 0; +} + +int +ACE_SOCK::get_local_addr (ACE_Addr &sa) const +{ + ACE_TRACE ("ACE_SOCK::get_local_addr"); + int len = sa.get_size (); + sockaddr *addr = (sockaddr *) sa.get_addr (); + + if (ACE_OS::getsockname (this->get_handle (), addr, &len) == -1) + return -1; + + sa.set_size ((int)len); + return 0; +} + +int +ACE_SOCK::open (int type, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK::open"); + this->set_handle (ACE_OS::socket (protocol_family, type, protocol)); + return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0; +} + +// Close down a ACE_SOCK. + +int +ACE_SOCK::close (void) +{ + ACE_TRACE ("ACE_SOCK::close"); + int result = 0; + + if (this->get_handle () != ACE_INVALID_HANDLE) + { + result = ACE_OS::closesocket (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + } + return result; +} + +// General purpose constructor for performing server ACE_SOCK +// creation. + +ACE_SOCK::ACE_SOCK (int type, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK::ACE_SOCK"); + if (this->open (type, protocol_family, protocol) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK::ACE_SOCK")); +} diff --git a/ace/SOCK.h b/ace/SOCK.h new file mode 100644 index 00000000000..25f2b580cfe --- /dev/null +++ b/ace/SOCK.h @@ -0,0 +1,95 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_H) +#define ACE_SOCK_H + +#include "ace/ACE.h" +#include "ace/Addr.h" +#include "ace/IPC_SAP.h" + +// 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) +#define ACE_SOCK_ACCEPTOR ACE_SOCK_Acceptor +#define ACE_SOCK_CONNECTOR ACE_SOCK_Connector +#define ACE_SOCK_STREAM ACE_SOCK_Stream +#else /* TEMPLATES are broken (must be a cfront-based compiler...) */ +#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 +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +class ACE_Export ACE_SOCK : public ACE_IPC_SAP + // = TITLE + // Defines the member functions for the base class of the + // ACE_SOCK abstraction. +{ +public: + int open (int type, + int protocol_family, + int protocol); + // Wrapper around the socket() system call. + + int set_option (int level, + int option, + void *optval, + int optlen) const; + // Wrapper around the setsockopt() system call. + + int get_option (int level, + int option, + void *optval, + int *optlen) const; + // Wrapper around the getsockopt() system call. + + int close (void); + // Close down the socket. + + int get_local_addr (ACE_Addr &) const; + // Return the local endpoint address. + + int get_remote_addr (ACE_Addr &) const; + // Return the address of the remotely connected peer (if there is + // one). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Make this an abstract class. + ACE_SOCK (void); + // Default constructor. + + ACE_SOCK (int type, int protocol_family, int protocol = 0); + // Wrapper around the socket() system call. + +#if defined (ACE_WIN32) + static ACE_SOCK dummy_; + // Used to ensure we initialize WinSock! +#endif /* ACE_WIN32 */ +}; + +#include "ace/SOCK.i" + +#endif /* ACE_SOCK_H */ diff --git a/ace/SOCK.i b/ace/SOCK.i new file mode 100644 index 00000000000..bbf4794a8af --- /dev/null +++ b/ace/SOCK.i @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK.i + +inline int +ACE_SOCK::set_option (int level, + int option, + void *optval, + int optlen) const +{ + ACE_TRACE ("ACE_SOCK::set_option"); + return ACE_OS::setsockopt (this->get_handle (), level, + option, (char *) optval, optlen); +} + +// Provides access to the ACE_OS::getsockopt system call. + +inline int +ACE_SOCK::get_option (int level, + int option, + void *optval, + int *optlen) const +{ + ACE_TRACE ("ACE_SOCK::get_option"); + return ACE_OS::getsockopt (this->get_handle (), level, + option, (char *) optval, optlen); +} diff --git a/ace/SOCK_Acceptor.cpp b/ace/SOCK_Acceptor.cpp new file mode 100644 index 00000000000..1a1e05fe536 --- /dev/null +++ b/ace/SOCK_Acceptor.cpp @@ -0,0 +1,125 @@ +// SOCK_Acceptor.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SOCK_Acceptor.h" +#include "ace/Log_Msg.h" + +#if !defined (__ACE_INLINE__) +#include "ace/SOCK_Acceptor.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Acceptor) + +// Do nothing routine for constructor. + +ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (void) +{ + ACE_TRACE ("ACE_SOCK_Acceptor::ACE_SOCK_Acceptor"); +} + +// General purpose routine for accepting new connections. + +int +ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, ACE_Addr *remote_addr, + ACE_Time_Value *timeout, int restart) const +{ + ACE_TRACE ("ACE_SOCK_Acceptor::accept"); + ACE_HANDLE new_handle = this->shared_accept (remote_addr, timeout, restart); + new_stream.set_handle (new_handle); + return new_handle == ACE_INVALID_HANDLE ? -1 : 0; +} + +// General purpose routine for performing server ACE_SOCK creation. + +ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (const ACE_Addr &local_sap, + int reuse_addr, + int protocol_family, + int backlog, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Acceptor::ACE_SOCK_Acceptor"); + if (this->open (local_sap, reuse_addr, protocol_family, + backlog, protocol) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK_Acceptor")); +} + +void +ACE_SOCK_Acceptor::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_Acceptor::dump"); +} + +// General purpose routine for performing server ACE_SOCK creation. + +int +ACE_SOCK_Acceptor::open (const ACE_Addr &local_sap, int reuse_addr, + int protocol_family, int backlog, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Acceptor::open"); + int one = 1; + int error = 0; + + if (ACE_SOCK::open (SOCK_STREAM, protocol_family, protocol) + == -1) + error = 1; + else if (reuse_addr && + this->set_option (SOL_SOCKET, SO_REUSEADDR, + &one, sizeof one) == -1) + error = 1; + else if (&local_sap == &ACE_Addr::sap_any + && protocol_family == PF_INET) + { + if (ACE::bind_port (this->get_handle ()) == -1) + error = 1; + } + else if (ACE_OS::bind (this->get_handle (), (sockaddr *) local_sap.get_addr (), + local_sap.get_size ()) == -1) + error = 1; + + if (error || ACE_OS::listen (this->get_handle (), backlog) == -1) + this->close (); + + return error ? -1 : 0; +} + +// Performs the timed accept operation. + +ACE_HANDLE +ACE_SOCK_Acceptor::shared_accept (ACE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart) const +{ + ACE_TRACE ("ACE_SOCK_Acceptor::shared_accept"); + sockaddr *addr = 0; + int *len_ptr = 0; + int len; + ACE_HANDLE new_handle; + + if (remote_addr != 0) + { + len = remote_addr->get_size (); + len_ptr = &len; + addr = (sockaddr *) remote_addr->get_addr (); + } + + // Handle the timeout case. + if (timeout != 0 && ACE::handle_timed_accept (this->get_handle (), timeout, restart) == -1) + return ACE_INVALID_HANDLE; + else + { + // Perform a blocking accept. + + do + new_handle = ACE_OS::accept (this->get_handle (), addr, len_ptr); + while (new_handle == ACE_INVALID_HANDLE && restart && errno == EINTR); + + // Reset the size of the addr (really only necessary for the + // UNIX domain sockets). + if (new_handle != ACE_INVALID_HANDLE && remote_addr != 0) + remote_addr->set_size (*len_ptr); + + return new_handle; + } +} diff --git a/ace/SOCK_Acceptor.h b/ace/SOCK_Acceptor.h new file mode 100644 index 00000000000..fd3c2534a92 --- /dev/null +++ b/ace/SOCK_Acceptor.h @@ -0,0 +1,81 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_Acceptor.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_ACCEPTOR_H) +#define ACE_SOCK_ACCEPTOR_H + +#include "ace/SOCK_Stream.h" +#include "ace/Time_Value.h" + +class ACE_Export ACE_SOCK_Acceptor : public ACE_SOCK + // = TITLE + // Defines the format and interface for an ACE_SOCK ACE_Stream acceptor. +{ +public: + // = Initialization methods. + ACE_SOCK_Acceptor (void); + // Default constructor. + + ACE_SOCK_Acceptor (const ACE_Addr &local_sap, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = 5, + int protocol = 0); + // Initiate a passive mode socket. + + int open (const ACE_Addr &local_sap, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = 5, + int protocol = 0); + // Initiate a passive mode socket. + + // = Passive connection acceptance method. + int accept (ACE_SOCK_Stream &new_stream, + ACE_Addr *remote_addr = 0, + ACE_Time_Value *timeout = 0, + int restart = 1) const; + // Accept a new data transfer connection. A <timeout> of 0 means + // block forever, a <timeout> of {0, 0} means poll. <restart> == 1 + // means "restart if interrupted." + + // = Meta-type info + typedef ACE_INET_Addr PEER_ADDR; + typedef ACE_SOCK_Stream PEER_STREAM; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_HANDLE shared_accept (ACE_Addr *remote_addr, + ACE_Time_Value *, + int restart) const; + // Shared by both the ACE_LSOCK_Acceptor and ACE_SOCK_Acceptor. + +private: + int get_remote_addr (ACE_Addr &) const; + // Do not allow this function to percolate up to this interface... +}; + +#if defined (__ACE_INLINE__) +#include "ace/SOCK_Acceptor.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SOCK_ACCEPTOR_H */ diff --git a/ace/SOCK_Acceptor.i b/ace/SOCK_Acceptor.i new file mode 100644 index 00000000000..06b6b01401c --- /dev/null +++ b/ace/SOCK_Acceptor.i @@ -0,0 +1,8 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_Acceptor.i + +#include "ace/Log_Msg.h" + + diff --git a/ace/SOCK_CODgram.cpp b/ace/SOCK_CODgram.cpp new file mode 100644 index 00000000000..c8c4d88a6f7 --- /dev/null +++ b/ace/SOCK_CODgram.cpp @@ -0,0 +1,100 @@ +// SOCK_CODgram.cpp +// $Id$ + +/* Contains the definitions for the ACE_SOCK connection-oriented + datagram abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/SOCK_CODgram.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_CODgram) + +void +ACE_SOCK_CODgram::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_CODgram::dump"); +} + +/* Here's the general-purpose constructor. */ + +ACE_SOCK_CODgram::ACE_SOCK_CODgram (const ACE_Addr &remote, const ACE_Addr &local, + int protocol_family, int protocol) +{ + ACE_TRACE ("ACE_SOCK_CODgram::ACE_SOCK_CODgram"); + if (this->open (remote, local, protocol_family, protocol) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK_CODgram")); +} + +/* This is the general-purpose open routine. Note that it performs + a different set of functions depending on the LOCAL and REMOTE + addresses passed to it. Here's the basic logic: + + 1. remote == ACE_Addr::sap_any && local == ACE_Addr::sap_any + if protocol_family == PF_INET then + bind the local address to a randomly generated port number... + + 2. remote == ACE_Addr::sap_any && local != ACE_Addr::sap_any + we are just binding the local address + (used primarily by servers) + + 3. remote != ACE_Addr::sap_any && local == ACE_Addr::sap_any + we are connecting to the remote address + (used primarily by clients) + + 4. remote != ACE_Addr::sap_any && local != ACE_Addr::sap_any + we are binding to the local address + and connecting to the remote address +*/ + +int +ACE_SOCK_CODgram::open (const ACE_Addr &remote, const ACE_Addr &local, + int protocol_family, int protocol) +{ + ACE_TRACE ("ACE_SOCK_CODgram::open"); + if (ACE_SOCK::open (SOCK_DGRAM, protocol_family, protocol) == -1) + return -1; + else + { + int error = 0; + + if (&local == &ACE_Addr::sap_any && &remote == &ACE_Addr::sap_any) + { + /* Assign an arbitrary port number from the transient range!! */ + + if (protocol_family == PF_INET + && ACE::bind_port (this->get_handle ()) == -1) + error = 1; + } + /* We are binding just the local address. */ + else if (&local != &ACE_Addr::sap_any && &remote == &ACE_Addr::sap_any) + { + if (ACE_OS::bind (this->get_handle (), (sockaddr *) local.get_addr (), + local.get_size ()) == -1) + error = 1; + } + /* We are connecting to the remote address. */ + else if (&local == &ACE_Addr::sap_any && &remote != &ACE_Addr::sap_any) + { + if (ACE_OS::connect (this->get_handle (), (sockaddr *) remote.get_addr (), + remote.get_size ()) == -1) + error = 1; + } + /* We are binding to the local address and connecting to the + remote addresses. */ + else + { + if (ACE_OS::bind (this->get_handle (), (sockaddr *) local.get_addr (), + local.get_size ()) == -1 + || ACE_OS::connect (this->get_handle (), (sockaddr *) remote.get_addr (), + remote.get_size ()) == -1) + error = 1; + } + if (error) + { + this->close (); + this->set_handle (ACE_INVALID_HANDLE); + } + return error ? -1 : 0; + } +} diff --git a/ace/SOCK_CODgram.h b/ace/SOCK_CODgram.h new file mode 100644 index 00000000000..008a5a6f60e --- /dev/null +++ b/ace/SOCK_CODgram.h @@ -0,0 +1,55 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_CODgram.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_CODGRAM_H) +#define ACE_SOCK_CODGRAM_H + +#include "ace/SOCK_IO.h" +#include "ace/Addr.h" + +class ACE_Export ACE_SOCK_CODgram : public ACE_SOCK_IO + // = TITLE + // Defines the member functions for the ACE_SOCK connected + // datagram abstraction. +{ +public: + // = Initialization methods. + ACE_SOCK_CODgram (void); + // Default constructor. + + ACE_SOCK_CODgram (const ACE_Addr &remote_sap, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int protocol_family = PF_INET, + int protocol = 0); + // Initiate a connected dgram. + + int open (const ACE_Addr &remote_sap, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int protocol_family = PF_INET, + int protocol = 0); + // Initiate a connected dgram. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/SOCK_CODgram.i" + +#endif /* ACE_SOCK_CODGRAM_H */ diff --git a/ace/SOCK_CODgram.i b/ace/SOCK_CODgram.i new file mode 100644 index 00000000000..8f72a5b117c --- /dev/null +++ b/ace/SOCK_CODgram.i @@ -0,0 +1,12 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_CODgram.i + +inline +ACE_SOCK_CODgram::ACE_SOCK_CODgram (void) +{ + ACE_TRACE ("ACE_SOCK_CODgram::ACE_SOCK_CODgram"); +} + + diff --git a/ace/SOCK_Connector.cpp b/ace/SOCK_Connector.cpp new file mode 100644 index 00000000000..ad904cd6c19 --- /dev/null +++ b/ace/SOCK_Connector.cpp @@ -0,0 +1,152 @@ +// SOCK_Connector.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/SOCK_Connector.h" +#include "ace/Handle_Set.h" +#include "ace/INET_Addr.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Connector) + +void +ACE_SOCK_Connector::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_Connector::dump"); +} + +// Actively connect and produce a new ACE_SOCK_Stream if things go well... + +int +ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Connector::connect"); + int result = 0; + + // Only open a new socket if we don't already have a valid handle. + if (new_stream.get_handle () == ACE_INVALID_HANDLE) + { + if (ACE_SOCK::open (SOCK_STREAM, protocol_family, protocol) == -1) + return -1; + } + else // Borrow the handle from the NEW_STREAM. + this->set_handle (new_stream.get_handle ()); + + sockaddr *raddr = (sockaddr *) remote_sap.get_addr (); + size_t rsize = remote_sap.get_size (); + + if (&local_sap != &ACE_Addr::sap_any) + { + // Bind the local endpoint to a specific addr. + + int one = 1; + if (reuse_addr && this->set_option (SOL_SOCKET, SO_REUSEADDR, + &one, sizeof one) == -1) + result = -1; + else + { + sockaddr *laddr = (sockaddr *) local_sap.get_addr (); + size_t size = local_sap.get_size (); + result = ACE_OS::bind (this->get_handle (), laddr, size); + } + if (result == -1) + { + this->close (); + return -1; + } + } + + // Enable non-blocking, if required. + if (timeout != 0) + { + if (this->enable (ACE_NONBLOCK) == -1) + result = -1; + + if (ACE_OS::connect (this->get_handle (), raddr, rsize) == -1) + { + result = -1; + + // Check whether the connection is in progress. + if (errno == EINPROGRESS || errno == EWOULDBLOCK) + { + // This expression checks if we were polling. + if (timeout->sec () == 0 && timeout->usec () == 0) + errno = EWOULDBLOCK; + // Wait synchronously + else if (this->complete (new_stream, 0, timeout) != -1) + return 0; + } + } + } + // Do a blocking connect. + else if (ACE_OS::connect (this->get_handle (), raddr, rsize) == -1) + result = -1; + + // EISCONN is treated specially since this routine may be used to check + // if we are already connected. + if (result != -1 || errno == EISCONN) + { + // If everything succeeded transfer ownership to <new_stream>. + new_stream.set_handle (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + } + else if (!(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + { + // If things have gone wrong, close down and return an error. + this->close (); + new_stream.set_handle (ACE_INVALID_HANDLE); + } + return result; +} + +// Try to complete a non-blocking connection. + +int +ACE_SOCK_Connector::complete (ACE_SOCK_Stream &new_stream, + ACE_Addr *remote_sap, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_SOCK_Connector::complete"); + ACE_HANDLE h = ACE::handle_timed_complete (this->get_handle (), tv); + + if (h == ACE_INVALID_HANDLE) + { + this->close (); + return -1; + } + else // We've successfully connected! + { + if (remote_sap != 0) + { + int len; + + len = remote_sap->get_size (); + sockaddr *addr = (sockaddr *) remote_sap->get_addr (); + + if (ACE_OS::getpeername (h, addr, &len) == -1) + { + this->close (); + return -1; + } + } + + // Transfer ownership. + new_stream.set_handle (this->get_handle ()); + + // Start out with non-blocking disabled on the <new_stream>. + new_stream.disable (ACE_NONBLOCK); + + this->set_handle (ACE_INVALID_HANDLE); + return 0; + } +} + + diff --git a/ace/SOCK_Connector.h b/ace/SOCK_Connector.h new file mode 100644 index 00000000000..226e862cb44 --- /dev/null +++ b/ace/SOCK_Connector.h @@ -0,0 +1,101 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_Connector.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_CONNECTOR_H) +#define ACE_SOCK_CONNECTOR_H + +#include "ace/SOCK_Stream.h" +#include "ace/Time_Value.h" + +class ACE_Export ACE_SOCK_Connector : public ACE_SOCK + // = TITLE + // Defines an active connection factory for the socket wrappers. +{ +public: + // = Initialization routines. + ACE_SOCK_Connector (void); + // Default constructor. + + ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = 0, + int perms = 0, + int protocol_family = PF_INET, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + int connect (ACE_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = 0, + int perms = 0, + int protcol_family = PF_INET, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + // = Completion routine. + int complete (ACE_SOCK_Stream &new_stream, + ACE_Addr *remote_sap = 0, + ACE_Time_Value *timeout = 0); + // Try to complete a non-blocking connection. + // If connection completion is successful then <new_stream> contains + // the connected ACE_SOCK_Stream. If <remote_sap> is non-NULL then it + // will contain the address of the connected peer. + + // = Meta-type info + typedef ACE_INET_Addr PEER_ADDR; + typedef ACE_SOCK_Stream PEER_STREAM; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/SOCK_Connector.i" + +#endif /* ACE_SOCK_CONNECTOR_H */ diff --git a/ace/SOCK_Connector.i b/ace/SOCK_Connector.i new file mode 100644 index 00000000000..391e2146e14 --- /dev/null +++ b/ace/SOCK_Connector.i @@ -0,0 +1,35 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_Connector.i + +#include "ace/Log_Msg.h" + +// This constructor is used by a client when it wants to connect to +// the specified REMOTE_SAP address using a blocking open. + +inline +ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector"); + if (this->connect (new_stream, remote_sap, timeout, local_sap, + reuse_addr, flags, perms, protocol_family, protocol) == -1 + && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK_Connector::ACE_SOCK_Connector")); +} + +// Do-nothing constructor... + +inline +ACE_SOCK_Connector::ACE_SOCK_Connector (void) +{ + ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector"); +} diff --git a/ace/SOCK_Dgram.cpp b/ace/SOCK_Dgram.cpp new file mode 100644 index 00000000000..e6ccde3b011 --- /dev/null +++ b/ace/SOCK_Dgram.cpp @@ -0,0 +1,118 @@ +// SOCK_Dgram.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/SOCK_Dgram.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram) + +void +ACE_SOCK_Dgram::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_Dgram::dump"); +} + +// Here's the shared open function. Note that if we are using the +// PF_INET protocol family and the address of LOCAL == the address of +// the special variable SAP_ANY then we are going to arbitrarily bind +// to a portnumber. + +int +ACE_SOCK_Dgram::shared_open (const ACE_Addr &local, int protocol_family) +{ + ACE_TRACE ("ACE_SOCK_Dgram::shared_open"); + int error = 0; + + if (&local == &ACE_Addr::sap_any && protocol_family == PF_INET) + { + if (ACE::bind_port (this->get_handle ()) == -1) + error = 1; + } + else if (ACE_OS::bind (this->get_handle (), (sockaddr *) local.get_addr (), + local.get_size ()) == -1) + error = 1; + + if (error) + this->close (); + + return error ? -1 : 0; +} + +// Here's the general-purpose constructor used by a connectionless +// datagram ``server''... + +ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, + int protocol_family, + int protocol) + : ACE_SOCK (SOCK_DGRAM, protocol_family, protocol) +{ + ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram"); + if (this->shared_open (local, protocol_family) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK_Dgram")); +} + +// Here's the general-purpose open routine. + +int +ACE_SOCK_Dgram::open (const ACE_Addr &local, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Dgram::open"); + if (ACE_SOCK::open (SOCK_DGRAM, protocol_family, + protocol) == -1) + return -1; + else + return this->shared_open (local, protocol_family); +} + +#if defined (ACE_HAS_MSG) +// Send an iovec of size N to ADDR as a datagram (connectionless +// version). + +ssize_t +ACE_SOCK_Dgram::send (const iovec iov[], + size_t n, + const ACE_Addr &addr, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram::send"); + msghdr send_msg; + + send_msg.msg_iov = (iovec *) iov; + send_msg.msg_iovlen = n; + send_msg.msg_name = (char *) addr.get_addr (); + send_msg.msg_namelen = addr.get_size (); + send_msg.msg_accrights = 0; + send_msg.msg_accrightslen = 0; + return ACE_OS::sendmsg (this->get_handle (), &send_msg, flags); +} + +// Recv an iovec of size N to ADDR as a datagram (connectionless +// version). + +ssize_t +ACE_SOCK_Dgram::recv (iovec iov[], + size_t n, + ACE_Addr &addr, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram::recv"); + msghdr recv_msg; + + recv_msg.msg_iov = (iovec *) iov; + recv_msg.msg_iovlen = n; + recv_msg.msg_name = (char *) addr.get_addr (); + recv_msg.msg_namelen = addr.get_size (); + recv_msg.msg_accrights = 0; + recv_msg.msg_accrightslen = 0; + + ssize_t status = ACE_OS::recvmsg (this->get_handle (), + &recv_msg, flags); + addr.set_size (recv_msg.msg_namelen); + return status; +} + +#endif /* ACE_HAS_MSG */ diff --git a/ace/SOCK_Dgram.h b/ace/SOCK_Dgram.h new file mode 100644 index 00000000000..7760a9e6356 --- /dev/null +++ b/ace/SOCK_Dgram.h @@ -0,0 +1,92 @@ +/* -*- C++ -*- */ +// $Id$ + + +// =========================================================================== +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_Dgram.h +// +// = AUTHOR +// Doug Schmidt +// +// =========================================================================== + +#if !defined (ACE_SOCK_DGRAM_H) +#define ACE_SOCK_DGRAM_H + +#include "ace/SOCK.h" +#include "ace/Addr.h" + +class ACE_Export ACE_SOCK_Dgram : public ACE_SOCK + // = TITLE + // Defines the member functions for the ACE_SOCK datagram + // abstraction. +{ +public: + // = Initialization routines. + ACE_SOCK_Dgram (void); + // Default constructor. + + ACE_SOCK_Dgram (const ACE_Addr &local, + int protocol_family = PF_INET, + int protocol = 0); + // Initiate a socket dgram. + + int open (const ACE_Addr &local, + int protocol_family = PF_INET, + int protocol = 0); + // Initiate a socket dgram. + + // = Data transfer routines. + ssize_t send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags = 0) const; + // Send an <n> byte <buf> to the datagram socket (uses sendto(3)). + + ssize_t recv (void *buf, + size_t n, + ACE_Addr &addr, + int flags = 0) const; + // Receive an <n> byte <buf> from the datagram socket (uses + // recvfrom(3)). + +#if defined (ACE_HAS_MSG) + ssize_t send (const iovec iov[], + size_t n, + const ACE_Addr &addr, + int flags = 0) const; + // Send an <iovec> of size <n> to the datagram socket (uses + // sendmsg(3)). + + ssize_t recv (iovec iov[], + size_t n, + ACE_Addr &addr, + int flags = 0) const; + // Recv an <iovec> of size <n> to the datagram socket (uses + // recvmsg(3)). +#endif /* ACE_HAS_MSG */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + int shared_open (const ACE_Addr &local, + int protocol_family); + // Open is shared by this and by <LSOCK_Dgram>. + +private: + int get_remote_addr (ACE_Addr &) const; + // Do not allow this function to percolate up to this interface... +}; + +#include "ace/SOCK_Dgram.i" + +#endif /* ACE_SOCK_DGRAM_H */ diff --git a/ace/SOCK_Dgram.i b/ace/SOCK_Dgram.i new file mode 100644 index 00000000000..e88d3906f4c --- /dev/null +++ b/ace/SOCK_Dgram.i @@ -0,0 +1,45 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_Dgram.i + +// Here's the simple-minded constructor. + +inline +ACE_SOCK_Dgram::ACE_SOCK_Dgram (void) +{ + ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram"); +} + +// Send an N byte datagram to ADDR (connectionless version). + +inline ssize_t +ACE_SOCK_Dgram::send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram::send"); + sockaddr *saddr = (sockaddr *) addr.get_addr (); + size_t len = addr.get_size (); + return ACE_OS::sendto (this->get_handle (), (const char *) buf, n, flags, + (struct sockaddr *) saddr, len); +} + +// Recv an n byte datagram to ADDR (connectionless version). + +inline ssize_t +ACE_SOCK_Dgram::recv (void *buf, + size_t n, + ACE_Addr &addr, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram::recv"); + sockaddr *saddr = (sockaddr *) addr.get_addr (); + int addr_len = addr.get_size (); + + ssize_t status = ACE_OS::recvfrom (this->get_handle (), (char *) buf, n, flags, + (sockaddr *) saddr, &addr_len); + addr.set_size (addr_len); + return status; +} diff --git a/ace/SOCK_Dgram_Bcast.cpp b/ace/SOCK_Dgram_Bcast.cpp new file mode 100644 index 00000000000..b38fe768e6f --- /dev/null +++ b/ace/SOCK_Dgram_Bcast.cpp @@ -0,0 +1,243 @@ +// SOCK_Dgram_Bcast.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/SOCK_Dgram_Bcast.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Bcast) + +ACE_Bcast_Node::ACE_Bcast_Node (ACE_INET_Addr &addr, + ACE_Bcast_Node *next) + : bcast_addr_ (addr), + next_ (next) +{ + ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node"); +} + +void +ACE_SOCK_Dgram_Bcast::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump"); +} + +// Close up and release resources. + +int +ACE_SOCK_Dgram_Bcast::close (void) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close"); + + ACE_Bcast_Node *temp = this->if_list_; + + // Release the dynamically allocated memory. + while (temp != 0) + { + ACE_Bcast_Node *hold = temp->next_; + delete temp; + temp = hold; + } + + // Shut down the descriptor. + return ACE_SOCK::close (); +} + +// Here's the simple-minded constructor. + +ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (void) + : if_list_ (0) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast"); +} + +// Here's the general-purpose constructor used by a connectionless +// datagram ``server''... + +ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (const ACE_Addr &local, + int protocol_family, + int protocol) + : ACE_SOCK_Dgram (local, protocol_family, protocol), + if_list_ (0) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast"); + + if (this->mk_broadcast () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK_Dgram_Bcast")); +} + +// Here's the general-purpose open routine. + +int +ACE_SOCK_Dgram_Bcast::open (const ACE_Addr &local, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::open"); + if (this->ACE_SOCK_Dgram::open (local, protocol_family, + protocol) == -1) + return -1; + + return this->mk_broadcast (); +} + +// Make broadcast available for Datagram socket. + +int +ACE_SOCK_Dgram_Bcast::mk_broadcast (void) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::mk_broadcast"); + + int one = 1; + + if (ACE_OS::setsockopt (this->get_handle (), SOL_SOCKET, SO_BROADCAST, + (char *) &one, sizeof one) == -1) + return -1; + +#if !defined(ACE_WIN32) + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq *ifr; + + struct ifreq flags; + struct ifreq if_req; + + int s = this->get_handle (); + + ifc.ifc_len = sizeof buf; + ifc.ifc_buf = buf; + + // Get interface structure and initialize the addresses using UNIX techniques. + if (ACE_OS::ioctl (s, SIOCGIFCONF, (char *) &ifc) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", + "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface configuration)"), + ACE_INVALID_HANDLE); + + ifr = ifc.ifc_req; + + for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0; n--, ifr++) + { + + if (ifr->ifr_addr.sa_family != AF_INET) + { + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SOCK_Dgram_Bcast::mk_broadcast: Not AF_INET")); + continue; + } + + flags = if_req = *ifr; + + if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)")); + continue; + } + + if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_UP) == 0) + { + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up")); + continue; + } + + if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK)) + continue; + + if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST)) + { + if (ACE_OS::ioctl (s, SIOCGIFBRDADDR, (char *) &if_req) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)")); + else + { + ACE_INET_Addr addr ((sockaddr_in *) &if_req.ifr_broadaddr, + sizeof if_req.ifr_broadaddr); + ACE_NEW_RETURN (this->if_list_, ACE_Bcast_Node (addr, this->if_list_), -1); + } + } + else + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface.")); + } +#else + ACE_INET_Addr addr (u_short (0), ACE_UINT32 (INADDR_BROADCAST)); + ACE_NEW_RETURN (this->if_list_, ACE_Bcast_Node (addr, this->if_list_), -1); +#endif /* !ACE_WIN32 */ + return this->if_list_ == 0 ? -1 : 0; +} + +// Broadcast the datagram to every interface. Returns the average +// number of bytes sent. + +ssize_t +ACE_SOCK_Dgram_Bcast::send (const void *buf, + size_t n, + u_short port_number, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send"); + size_t iterations = 0; + ssize_t total_bytes = 0; + + if (this->if_list_ == 0) + return -1; + + for (ACE_Bcast_Node *temp = this->if_list_; + temp != 0; + temp = temp->next_) + { + temp->bcast_addr_.set_port_number (port_number); + + ssize_t bytes_sent = ACE_SOCK_Dgram::send (buf, n, + temp->bcast_addr_, + flags); + + if (bytes_sent == -1) + return -1; + else + total_bytes += bytes_sent; + + iterations++; + } + + return iterations == 0 ? 0 : total_bytes / iterations; +} + +#if defined (ACE_HAS_MSG) +// Broadcast datagram to every interfaces. + +ssize_t +ACE_SOCK_Dgram_Bcast::send (const iovec iov[], + size_t n, + u_short port_number, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send"); + + if (this->if_list_ == 0) + return -1; + + // Send the message to every interface. + + for (ACE_Bcast_Node *temp = this->if_list_; temp != 0; temp++) + if (ACE_SOCK_Dgram::send (iov, n, temp->bcast_addr_, flags) == -1) + return -1; + + return 0; +} + +// Broadcast an ACE_IO_Vector of size N to ADDR as a datagram (note +// that addr must be preassigned to the broadcast address of the +// subnet...). + +ssize_t +ACE_SOCK_Dgram_Bcast::send (const iovec iov[], + size_t n, + const ACE_Addr &addr, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send"); + + return ACE_SOCK_Dgram::send (iov, n, addr, flags); +} +#endif /* ACE_HAS_MSG */ diff --git a/ace/SOCK_Dgram_Bcast.h b/ace/SOCK_Dgram_Bcast.h new file mode 100644 index 00000000000..f44270a37a9 --- /dev/null +++ b/ace/SOCK_Dgram_Bcast.h @@ -0,0 +1,106 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ + +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_Dgram_Bcast.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_DGRAM_BCAST_H) +#define ACE_SOCK_DGRAM_BCAST_H + +#include "ace/INET_Addr.h" +#include "ace/SOCK_Dgram.h" + +struct ACE_Bcast_Node +{ + ACE_Bcast_Node (ACE_INET_Addr &, ACE_Bcast_Node *); + + ACE_INET_Addr bcast_addr_; + // Broadcast address for the interface. + + ACE_Bcast_Node *next_; + // Pointer to the next interface in the chain. +}; + +class ACE_Export ACE_SOCK_Dgram_Bcast : public ACE_SOCK_Dgram + // = TITLE + // Defines the member functions for the ACE_SOCK datagram + // abstraction. +{ +public: + // = Initialization and termination methods. + ACE_SOCK_Dgram_Bcast (void); + // Default constructor. + + ACE_SOCK_Dgram_Bcast (const ACE_Addr &local, + int protocol_family = PF_INET, + int protocol = 0); + // Initiate a connectionless datagram broadcast endpoint. + + int open (const ACE_Addr &local, + int protocol_family = PF_INET, + int protocol = 0); + // Initiate a connectionless datagram broadcast endpoint. + + int close (void); + // Close up and release dynamically allocated resources. + + ssize_t send (const void *buf, + size_t n, + u_short portnum, + int flags = 0) const; + // Broadcast the datagram to every interface. Returns the average + // number of bytes sent. + + ssize_t send (const iovec iov[], + size_t n, + u_short portnum, + int flags = 0) const; + // Broadcast the <iovec> datagrams to every interface. Returns the + // average number of bytes sent. + + ssize_t send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags = 0) const; + // Broadcast an N byte datagram to ADDR (note that addr must be + // preassigned to the broadcast address of the subnet...). + + ssize_t send (const iovec iov[], + size_t n, + const ACE_Addr &addr, + int flags = 0) const; + // Broadcast an <iovec> of size <n> to <addr> as a datagram (note + // that addr must be preassigned to the broadcast address of the + // subnet...) */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int mk_broadcast (void); + // Make broadcast available for Datagram socket. + + ACE_Bcast_Node *if_list_; + // Points to the head of the list of broadcast interfaces. + + int get_remote_addr (ACE_Addr &) const; + // Do not allow this function to percolate up to this interface... +}; + +#include "ace/SOCK_Dgram_Bcast.i" + +#endif /* ACE_SOCK_DGRAM_BCAST_H */ diff --git a/ace/SOCK_Dgram_Bcast.i b/ace/SOCK_Dgram_Bcast.i new file mode 100644 index 00000000000..8029354e2ae --- /dev/null +++ b/ace/SOCK_Dgram_Bcast.i @@ -0,0 +1,23 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_Dgram_Bcast.i + +// Broadcast an N byte datagram to ADDR (note that addr must be +// preassigned to the broadcast address of the subnet...) + +inline ssize_t +ACE_SOCK_Dgram_Bcast::send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send"); + + sockaddr *saddr = (sockaddr *) addr.get_addr (); + size_t len = addr.get_size (); + return ACE_OS::sendto (this->get_handle (), (const char *) buf, n, flags, + (struct sockaddr *) saddr, len); +} + + diff --git a/ace/SOCK_Dgram_Mcast.cpp b/ace/SOCK_Dgram_Mcast.cpp new file mode 100644 index 00000000000..9401653edc1 --- /dev/null +++ b/ace/SOCK_Dgram_Mcast.cpp @@ -0,0 +1,108 @@ +// SOCK_Dgram_Mcast.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SOCK_Dgram_Mcast.h" +#include "ace/INET_Addr.h" + +#if defined (ACE_HAS_IP_MULTICAST) + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Mcast) + +void +ACE_SOCK_Dgram_Mcast::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::dump"); +} + +// Dummy default constructor... + +ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast (void) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::ACE_SOCK_Dgram_Mcast"); +} + +int +ACE_SOCK_Dgram_Mcast::subscribe (const ACE_INET_Addr &mcast_addr, + int reuse_addr, + const char *net_if, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::subscribe"); + // make a local copy of address to use in sends + this->mcast_addr_.set (mcast_addr); + + if (this->ACE_SOCK::open (SOCK_DGRAM, protocol_family, protocol) == -1) + return -1; + + // Create multicast request. + if (this->make_multicast_address (this->mcast_addr_, net_if) == -1) + return -1; + + int one = 1; + if (reuse_addr + && this->ACE_SOCK::set_option (SOL_SOCKET, + SO_REUSEADDR, + &one, + sizeof one) == -1) + return -1; + + // Create an address to bind the socket to. + + ACE_INET_Addr local; + + if (local.set (this->mcast_addr_.get_port_number ()) == -1) + return -1; + else if (ACE_SOCK_Dgram::shared_open (local, protocol_family) == -1) + return -1; + + // Tell network device driver to read datagrams with a + // multicast_address address. + else if (this->ACE_SOCK::set_option (IPPROTO_IP, + IP_ADD_MEMBERSHIP, + &multicast_address_, + sizeof multicast_address_) == -1) + return -1; + return 0; +} + +int +ACE_SOCK_Dgram_Mcast::unsubscribe (void) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::unsubscribe"); + return this->ACE_SOCK::set_option (IPPROTO_IP, + IP_DROP_MEMBERSHIP, + &multicast_address_, + sizeof multicast_address_); +} + +int +ACE_SOCK_Dgram_Mcast::make_multicast_address (const ACE_INET_Addr &mcast_addr, + const char *net_if) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::make_multicast_address"); + +#if !defined (ACE_WIN32) + if (net_if != 0) + { + struct ifreq if_address; + + ACE_OS::strcpy (if_address.ifr_name, net_if); + + if (ACE_OS::ioctl (this->get_handle (), SIOCGIFADDR, &if_address) < 0) + return -1; + + struct sockaddr_in *socket_address; + socket_address = (sockaddr_in *) &if_address.ifr_addr; + multicast_address_.imr_interface.s_addr = socket_address->sin_addr.s_addr; + } + else +#endif /* ACE_WIN32 */ + multicast_address_.imr_interface.s_addr = INADDR_ANY; + + multicast_address_.imr_multiaddr.s_addr = htonl (mcast_addr.get_ip_address ()); + // multicast_address_.imr_multiaddr.s_addr = mcast_addr.get_ip_address (); + return 0; +} +#endif /* ACE_HAS_IP_MULTICAST */ diff --git a/ace/SOCK_Dgram_Mcast.h b/ace/SOCK_Dgram_Mcast.h new file mode 100644 index 00000000000..586627e8a12 --- /dev/null +++ b/ace/SOCK_Dgram_Mcast.h @@ -0,0 +1,112 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_Dgram_Mcast.h +// +// = AUTHORS +// Irfan Pyrali (ip1@cs.wustl.edu) +// Tim Harrison (harrison@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (ACE_SOCK_DGRAM_MCAST_H) +#define ACE_SOCK_DGRAM_MCAST_H + +#include "ace/SOCK_Dgram.h" +#include "ace/INET_Addr.h" + +#if defined (ACE_HAS_IP_MULTICAST) +class ACE_Export ACE_SOCK_Dgram_Mcast : public ACE_SOCK_Dgram + // = TITLE + // Defines the member functions for the ACE_SOCK multicast abstraction. +{ +public: + // = Initialization routine. + ACE_SOCK_Dgram_Mcast (void); + // Note that there is no open (). This cannot be used unless you + // subscribe to the multicast group. If you just want to send (and + // not listen) to the multicast group, use ACE_SOCK_Dgram or + // ACE_SOCK_CODgram. + + // = Multicast group management routines. + + int subscribe (const ACE_INET_Addr &mcast_addr, + int reuse_addr = 1, + const char *net_if = 0, + int protocol_family = PF_INET, + int protocol = 0); + // Join a multicast group by telling the network interface device + // driver to accept datagrams with ACE_INET_Addr &mcast_addr + // multicast addresses. + // + // If you have called open already, subscribe closes the socket and + // opens a new socket bound to the mcast_addr. + // + // Interface is hardware specific. use netstat -i to find whether + // your interface is, say, le0 or something else. If net_if == 0, + // subscribe uses the default mcast interface. + // Returns: -1 on error, else 0. + + int unsubscribe (void); + // Unsubscribe from a multicast group. Returns 0 on success, -1 on + // failure. + + // = Data transfer routines. + ssize_t send (const void *buf, size_t n, int flags = 0) const; + // Send <n> bytes in <buf>. + + ssize_t send (const iovec iov[], size_t n, int flags = 0) const; + // Send <n> <iovecs>. + + // = Options. + int set_option (int option, char optval); + // Set an ip option that takes a char as input. + // e.g. IP_MULTICAST_LOOP. This is just a nice interface to a + // subset of possible setsockopt/ACE_SOCK::set_option calls Returns + // 0 on success, -1 on failure. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_HANDLE open (const ACE_Addr &local, + int protocol_family = PF_INET, + int protocol = 0); + // disable public use of ACE_SOCK_Dgram::open () + + // = Disable public use of ACE_SOCK_Dgram::sends and force + // ACE_SOCK_Dgram_Mcast::sends inline + ssize_t send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags = 0) const; + ssize_t send (const iovec iov[], + size_t n, + const ACE_Addr &addr, + int flags = 0) const; + + int make_multicast_address (const ACE_INET_Addr &mcast_addr, + const char *net_if = "le0"); + // Initialize a multicast address. + + ACE_INET_Addr mcast_addr_; + // Multicast group address. + + struct ip_mreq multicast_address_; + // IP address. +}; + +#include "ace/SOCK_Dgram_Mcast.i" + +#endif /* ACE_HAS_IP_MULTICAST */ +#endif /* ACE_SOCK_DGRAM_MCAST_H */ diff --git a/ace/SOCK_Dgram_Mcast.i b/ace/SOCK_Dgram_Mcast.i new file mode 100644 index 00000000000..835a3bbd135 --- /dev/null +++ b/ace/SOCK_Dgram_Mcast.i @@ -0,0 +1,31 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_Dgram_Mcast.i + +inline int +ACE_SOCK_Dgram_Mcast::set_option (int option, + char optval) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::set_option"); + return this->ACE_SOCK::set_option (IPPROTO_IP, option, + &optval, sizeof (char)); +} + +inline ssize_t +ACE_SOCK_Dgram_Mcast::send (const void *buf, + size_t n, int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send"); + return this->ACE_SOCK_Dgram::send (buf, n, + this->mcast_addr_, flags); +} + +inline ssize_t +ACE_SOCK_Dgram_Mcast::send (const iovec iov[], + size_t n, int flags) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast::send"); + return this->ACE_SOCK_Dgram::send (iov, n, + this->mcast_addr_, flags); +} diff --git a/ace/SOCK_IO.cpp b/ace/SOCK_IO.cpp new file mode 100644 index 00000000000..a09be6ce5a6 --- /dev/null +++ b/ace/SOCK_IO.cpp @@ -0,0 +1,114 @@ +// SOCK_IO.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SOCK_IO.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_IO) + +void +ACE_SOCK_IO::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_IO::dump"); +} + +// Allows a client to read from a socket without having to provide +// a buffer to read. This method determines how much data is in the +// socket, allocates a buffer of this size, reads in the data, and +// returns the number of bytes read. + +ssize_t +ACE_SOCK_IO::recv (iovec *io_vec) +{ +#if defined (FIONREAD) + u_long inlen; + + if (ACE_OS::ioctl (this->get_handle (), FIONREAD, + (u_long *) &inlen) == -1) + return -1; + else if (inlen > 0) + { + io_vec->iov_base = new char[inlen]; + io_vec->iov_len = this->recv (io_vec->iov_base, inlen); + return io_vec->iov_len; + } + else +#endif /* FIONREAD */ + // Could return ACE_NOTSUP_RETURN + return 0; +} + +// Send N char *ptrs and int lengths. Note that the char *'s precede +// the ints (basically, an varargs version of writev). The count N is +// the *total* number of trailing arguments, *not* a couple of the +// number of tuple pairs! + +ssize_t +ACE_SOCK_IO::send (size_t n, ...) const +{ + ACE_TRACE ("ACE_SOCK_IO::send"); + + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::writev (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + +// This is basically an interface to ACE_OS::readv, that doesn't use +// the struct iovec explicitly. The ... can be passed as an arbitrary +// number of (char *ptr, int len) tuples. However, the count N is the +// *total* number of trailing arguments, *not* a couple of the number +// of tuple pairs! + +ssize_t +ACE_SOCK_IO::recv (size_t n, ...) const +{ + ACE_TRACE ("ACE_SOCK_IO::recv"); + + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::readv (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + diff --git a/ace/SOCK_IO.h b/ace/SOCK_IO.h new file mode 100644 index 00000000000..bc60e050a64 --- /dev/null +++ b/ace/SOCK_IO.h @@ -0,0 +1,74 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_IO.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_IO_H) +#define ACE_SOCK_IO_H + +#include "ace/SOCK.h" + +class ACE_Export ACE_SOCK_IO : public ACE_SOCK + // = TITLE + // Defines the methods for the ACE_SOCK I/O routines (i.e., send/recv). +{ +public: + ssize_t send (const void *buf, size_t n, int flags) const; + // Send an n byte buffer to the connected socket (uses send(3)). + + ssize_t recv (void *buf, size_t n, int flags) const; + // Recv an n byte buffer from the connected socket (uses recv(3)). + + ssize_t send (const void *buf, size_t n) const; + // Send an n byte buffer to the connected socket (uses write(2)). + + ssize_t recv (void *buf, size_t n) const; + // Recv an n byte buffer from the connected socket (uses read(2)). + + ssize_t send (const iovec iov[], size_t n) const; + // Send a vector of n byte messages to the connected socket. + + ssize_t recv (iovec iov[], size_t n) const; + // Recv a vector of n byte messages to the connected socket. + + ssize_t send (size_t n, ...) const; + // Send varargs messages to the connected socket. + + ssize_t recv (size_t n, ...) const; + // Recv varargs messages to the connected socket. + + ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Send <n> bytes via Win32 WriteFile using overlapped I/O. + + ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Recv <n> bytes via Win32 ReadFile using overlapped I/O. + + ssize_t recv (iovec *io_vec); + // Allows a client to read from a socket without having to provide a + // buffer to read. This method determines how much data is in the + // socket, allocates a buffer of this size, reads in the data, and + // returns the number of bytes read. The caller is responsible for + // deleting the memory. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/SOCK_IO.i" + +#endif /* ACE_SOCK_IO_H */ diff --git a/ace/SOCK_IO.i b/ace/SOCK_IO.i new file mode 100644 index 00000000000..bfc6450d286 --- /dev/null +++ b/ace/SOCK_IO.i @@ -0,0 +1,85 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_IO.i + +// Send an n byte message to the connected socket. + +inline ssize_t +ACE_SOCK_IO::send (const void *buf, size_t n, int flags) const +{ + ACE_TRACE ("ACE_SOCK_IO::send"); + return ACE_OS::send (this->get_handle (), (const char *) buf, n, flags); +} + +// Recv an n byte message from the connected socket. + +inline ssize_t +ACE_SOCK_IO::recv (void *buf, size_t n, int flags) const +{ + ACE_TRACE ("ACE_SOCK_IO::recv"); + return ACE_OS::recv (this->get_handle (), (char *) buf, n, flags); +} + +// Send an n byte message to the connected socket. + +inline ssize_t +ACE_SOCK_IO::send (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_SOCK_IO::send"); +#if defined (ACE_WIN32) + return ACE_OS::send (this->get_handle (), (const char *) buf, n, 0); +#else + return ACE_OS::write (this->get_handle (), (const char *) buf, n); +#endif /* ACE_WIN32 */ +} + +// Recv an n byte message from the connected socket. + +inline ssize_t +ACE_SOCK_IO::recv (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_SOCK_IO::recv"); +#if defined (ACE_WIN32) + return ACE_OS::recv (this->get_handle (), (char *) buf, n, 0); +#else + return ACE_OS::read (this->get_handle (), (char *) buf, n); +#endif /* ACE_WIN32 */ +} + +// Send a vector of n byte messages to the connected socket. + +inline ssize_t +ACE_SOCK_IO::send (const iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_SOCK_IO::send"); + return ACE_OS::writev (this->get_handle (), (iovec *) iov, n); +} + +// Recv an n byte message from the connected socket. + +inline ssize_t +ACE_SOCK_IO::recv (iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_SOCK_IO::recv"); + return ACE_OS::readv (this->get_handle (), (iovec *) iov, n); +} + +inline ssize_t +ACE_SOCK_IO::send (const void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_SOCK_IO::send"); + return ACE_OS::write (this->get_handle (), + (const char *) buf, n, + overlapped); +} + +inline ssize_t +ACE_SOCK_IO::recv (void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_SOCK_IO::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n, + overlapped); +} diff --git a/ace/SOCK_Stream.cpp b/ace/SOCK_Stream.cpp new file mode 100644 index 00000000000..0dc237200a9 --- /dev/null +++ b/ace/SOCK_Stream.cpp @@ -0,0 +1,16 @@ +// SOCK_Stream.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SOCK_Stream.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Stream) + +void +ACE_SOCK_Stream::dump (void) const +{ + ACE_TRACE ("ACE_SOCK_Stream::dump"); +} + + + diff --git a/ace/SOCK_Stream.h b/ace/SOCK_Stream.h new file mode 100644 index 00000000000..3eceece50c2 --- /dev/null +++ b/ace/SOCK_Stream.h @@ -0,0 +1,69 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SOCK_Stream.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SOCK_STREAM_H) +#define ACE_SOCK_STREAM_H + +#include "ace/SOCK_IO.h" +#include "ace/INET_Addr.h" + +class ACE_Export ACE_SOCK_Stream : public ACE_SOCK_IO + // = TITLE + // Defines the methods in the <ACE_SOCK_Stream> abstraction. + // + // = DESCRIPTION + // This adds additional wrapper methods atop the <ACE_SOCK_IO> class. +{ +public: + //= The following two methods use write and read system calls, + //= which are faster than the send and recv library functions + //= used by the following two methods. + ssize_t send_n (const void *buf, int n) const; + // Send n bytes, keep trying until n are sent. + ssize_t recv_n (void *buf, int n) const; + // Recv n bytes, keep trying until n are received. + + // = The following two methods use the send and recv system + // = calls. + ssize_t send_n (const void *buf, int n, int flags) const; + // Send n bytes, keep trying until n are sent. + ssize_t recv_n (void *buf, int n, int flags) const; + // Recv n bytes, keep trying until n are received. + + // = Send/receive an ``urgent'' character (see TCP specs...). + ssize_t send_urg (void *ptr, int len = sizeof (char)); + ssize_t recv_urg (void *ptr, int len = sizeof (char)); + + // = Selectively close endpoints. + int close_reader (void); + // Close down the reader. + int close_writer (void); + // Close down the writer. + + // = Meta-type info + typedef ACE_INET_Addr PEER_ADDR; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/SOCK_Stream.i" + +#endif /* ACE_SOCK_STREAM_H */ diff --git a/ace/SOCK_Stream.i b/ace/SOCK_Stream.i new file mode 100644 index 00000000000..cd703bb834c --- /dev/null +++ b/ace/SOCK_Stream.i @@ -0,0 +1,81 @@ +/* -*- C++ -*- */ +// $Id$ + +// SOCK_Stream.i + +#include "ace/SOCK_Stream.h" + +// Shut down just the reading end of a ACE_SOCK. + +inline int +ACE_SOCK_Stream::close_reader (void) +{ + ACE_TRACE ("ACE_SOCK_Stream::close_reader"); + int result = ACE_OS::shutdown (this->get_handle (), 0); + return result; +} + +// Shut down just the writing end of a ACE_SOCK. + +inline int +ACE_SOCK_Stream::close_writer (void) +{ + ACE_TRACE ("ACE_SOCK_Stream::close_writer"); + int result = ACE_OS::shutdown (this->get_handle (), 1); + return result; +} + +// Receive exactly BUF_SIZE bytes from file descriptor this->handle +// into <buf>. Keep trying until this many bytes are received. + +inline ssize_t +ACE_SOCK_Stream::recv_n (void *buf, int buf_size, int flags) const +{ + ACE_TRACE ("ACE_SOCK_Stream::recv_n"); + return ACE::recv_n (this->get_handle (), buf, buf_size, flags); +} + +// Send exactly N bytes from <buf> to <handle>. Keeping trying +// until this many bytes are sent. + +inline ssize_t +ACE_SOCK_Stream::send_n (const void *buf, int buf_size, int flags) const +{ + ACE_TRACE ("ACE_SOCK_Stream::send_n"); + return ACE::send_n (this->get_handle (), buf, buf_size, flags); +} + +// Receive exactly BUF_SIZE bytes from file descriptor +// into BUF. Keep trying until this many bytes are received. + +inline ssize_t +ACE_SOCK_Stream::recv_n (void *buf, int buf_size) const +{ + ACE_TRACE ("ACE_SOCK_Stream::recv_n"); + return ACE::recv_n (this->get_handle (), buf, buf_size); +} + +// Send exactly N bytes from BUF to THIS->SOK_FD. Keeping trying +// until this many bytes are sent. + +inline ssize_t +ACE_SOCK_Stream::send_n (const void *buf, int buf_size) const +{ + ACE_TRACE ("ACE_SOCK_Stream::send_n"); + return ACE::send_n (this->get_handle (), buf, buf_size); +} + +inline ssize_t +ACE_SOCK_Stream::send_urg (void *ptr, int len) +{ + ACE_TRACE ("ACE_SOCK_Stream::send_urg"); + return ACE_OS::send (this->get_handle (), (char *) ptr, len, MSG_OOB); +} + +inline ssize_t +ACE_SOCK_Stream::recv_urg (void *ptr, int len) +{ + ACE_TRACE ("ACE_SOCK_Stream::recv_urg"); + return ACE_OS::recv (this->get_handle (), (char *) ptr, len, MSG_OOB); +} + diff --git a/ace/SPIPE.cpp b/ace/SPIPE.cpp new file mode 100644 index 00000000000..ff52532a8e6 --- /dev/null +++ b/ace/SPIPE.cpp @@ -0,0 +1,58 @@ +// SPIPE.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SPIPE.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE) + +// This is the do-nothing constructor. + +ACE_SPIPE::ACE_SPIPE (void) +{ + ACE_TRACE ("ACE_SPIPE::ACE_SPIPE"); +} + +void +ACE_SPIPE::dump (void) const +{ + ACE_TRACE ("ACE_SPIPE::dump"); +} + +// Close down a ACE_SPIPE. + +int +ACE_SPIPE::get_local_addr (ACE_SPIPE_Addr &local_sap) const +{ + ACE_TRACE ("ACE_SPIPE::get_local_addr"); + local_sap = this->local_addr_; + return 0; +} + +// Close down the STREAM pipe without removing the rendezvous point. + +int +ACE_SPIPE::close (void) +{ + ACE_TRACE ("ACE_SPIPE::close"); + int result = 0; + + if (this->get_handle () != ACE_INVALID_HANDLE) + { + result = ACE_OS::close (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + } + return result; +} + +// Close down the STREAM pipe and remove the rendezvous point from the +// file system. + +int +ACE_SPIPE::remove (void) +{ + ACE_TRACE ("ACE_SPIPE::remove"); + int result = this->close (); + return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1 || result == -1 ? -1 : 0; +} + diff --git a/ace/SPIPE.h b/ace/SPIPE.h new file mode 100644 index 00000000000..527e5388616 --- /dev/null +++ b/ace/SPIPE.h @@ -0,0 +1,76 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SPIPE.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SPIPE_H) +#define ACE_SPIPE_H + +#include "ace/IPC_SAP.h" +#include "ace/SPIPE_Addr.h" + +// 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) +#define ACE_SPIPE_ACCEPTOR ACE_SPIPE_Acceptor +#define ACE_SPIPE_CONNECTOR ACE_SPIPE_Connector +#define ACE_SPIPE_STREAM ACE_SPIPE_Stream +#define ACE_UPIPE_ACCEPTOR ACE_UPIPE_Acceptor +#define ACE_UPIPE_CONNECTOR ACE_UPIPE_Connector +#define ACE_UPIPE_STREAM ACE_UPIPE_Stream +#else /* TEMPLATES are broken (must be a cfront-based compiler...) */ +#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 +#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 +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +class ACE_Export ACE_SPIPE : public ACE_IPC_SAP + // = TITLE + // Defines the member functions for the base class of the + // ACE_SPIPE abstraction. +{ +public: + int close (void); + // Close down the STREAM pipe without removing the rendezvous point. + + int remove (void); + // Close down the STREAM pipe and remove the rendezvous point from + // the file system. + + int get_local_addr (ACE_SPIPE_Addr &) const; + // Return the local address of this endpoint. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_SPIPE (void); + // Ensure that this class is an abstract base class + + ACE_SPIPE_Addr local_addr_; + // Our local address. +}; + +#include "ace/SPIPE.i" +#endif /* ACE_SPIPE_H */ diff --git a/ace/SPIPE.i b/ace/SPIPE.i new file mode 100644 index 00000000000..d2db9a084c8 --- /dev/null +++ b/ace/SPIPE.i @@ -0,0 +1,6 @@ +/* -*- C++ -*- */ +// $Id$ + +// SPIPE.i + + diff --git a/ace/SPIPE_Acceptor.cpp b/ace/SPIPE_Acceptor.cpp new file mode 100644 index 00000000000..c3d7458257d --- /dev/null +++ b/ace/SPIPE_Acceptor.cpp @@ -0,0 +1,212 @@ +// SPIPE_Acceptor.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SPIPE_Acceptor.h" +#include "ace/Log_Msg.h" + +ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (void) +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor"); +} + +int +ACE_SPIPE_Acceptor::remove (void) +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::remove"); + int result = this->close (); +#if defined (ACE_HAS_STREAM_PIPES) + // Remove the underlying file. + return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1 + || result == -1 ? -1 : 0; +#else + return 0; +#endif +} + +ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Acceptor) + +void +ACE_SPIPE_Acceptor::dump (void) const +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::dump"); +} + +// General purpose routine for performing server ACE_SPIPE creation. + +int +ACE_SPIPE_Acceptor::open (const ACE_SPIPE_Addr &local_sap, + int reuse_addr, + int perms) +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::open"); + + this->local_addr_ = local_sap; + this->set_handle (ACE_INVALID_HANDLE); + + return this->create_new_instance (perms); +} + +int +ACE_SPIPE_Acceptor::create_new_instance (int perms) +{ +#if defined (ACE_HAS_STREAM_PIPES) + ACE_HANDLE handle; + ACE_HANDLE spipe[2]; + + handle = ACE_OS::creat (this->local_addr_.get_path_name (), perms); + + if (handle == ACE_INVALID_HANDLE) + return -1; + else if (ACE_OS::close (handle) == -1) + return -1; + else if (ACE_OS::pipe (spipe) == -1) + return -1; + else if (ACE_OS::ioctl (spipe[0], I_PUSH, "connld") == -1) + return -1; + else if (ACE_OS::fattach (spipe[0], this->local_addr_.get_path_name ()) == -1) + return -1; + + this->set_handle (spipe[1]); + return 0; +#elif defined (ACE_WIN32) + // Create a new instance of the Named Pipe (WIN32). A new instance + // of the named pipe must be created for every client process. If an + // instance of the named pipe that is already connected to a client + // process is reused with a new client process, ::ConnectNamedPipe() + // would fail. + + ACE_TRACE ("ACE_SPIPE_Acceptor::create_new_instance"); + + // Create a new instance of the named pipe + ACE_HANDLE handle = ::CreateNamedPipe (this->local_addr_.get_path_name (), + PIPE_ACCESS_DUPLEX | + FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, + MAX_PIPE_INSTANCES, + 1024*10, + 1024*10, + ACE_DEFAULT_TIMEOUT, + NULL); + if (handle == ACE_INVALID_HANDLE) + return -1; + else + this->set_handle (handle); + return 0; +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +int +ACE_SPIPE_Acceptor::close (void) +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::close"); + + // This behavior is shared by UNIX and Win32... + int result = this->ACE_SPIPE::close (); + this->set_handle (ACE_INVALID_HANDLE); + +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OS::fdetach (this->local_addr_.get_path_name ()); +#endif /* ACE_HAS_STREAM_PIPES */ + return result; +} + +ACE_INLINE +ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap, + int reuse_addr, + int perms) +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor"); + + if (this->open (local_sap, reuse_addr, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SPIPE_Acceptor")); +} + +// General purpose routine for accepting new connections. + +int +ACE_SPIPE_Acceptor::accept (ACE_SPIPE_Stream &new_io, + ACE_SPIPE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart) +{ + ACE_TRACE ("ACE_SPIPE_Acceptor::accept"); +#if defined (ACE_HAS_STREAM_PIPES) + strrecvfd r_handle; + + // Note that if THIS->MILLI_SECOND_DELAY == -1 we block on + // ACE_OS::ioctl(). Otherwise, we will wait for the desired number + // of milli seconds using ACE_OS::poll. + + if (timeout != 0 && + ACE::handle_timed_accept (this->get_handle (), timeout, restart) == -1) + return -1; + else if (ACE_OS::ioctl (this->get_handle (), I_RECVFD, &r_handle) == -1) + return -1; + + new_io.set_handle (r_handle.fd); + new_io.local_addr_ = this->local_addr_; + new_io.remote_addr_.set_size (sizeof r_handle.gid + sizeof r_handle.uid); + new_io.remote_addr_.group_id (r_handle.gid); + new_io.remote_addr_.user_id (r_handle.uid); + + // This is for compatibility with ACE_SOCK_Acceptor and + // ACE_TLI_Acceptor. + if (remote_addr != 0) + *remote_addr = new_io.remote_addr_; + + return 0; +#elif defined (ACE_WIN32) + // Check to see if we have a valid pipe + if (this->get_handle () == ACE_INVALID_HANDLE) + return -1; + + // Accept connection on the current instance of the named pipe Note + // that the connection is done synchronously, by specifying a NULL + // OVERLAPPED structure pointer. + + int attempts = 0; + + for (;;) + { + attempts++; + + if (::ConnectNamedPipe (this->get_handle (), NULL) != 0) + break; + + DWORD error = ::GetLastError (); + + if (error == ERROR_NO_DATA) + { + // A client connected and disconnected in the interval + // between the creation of the named pipe instance and the + // call to ::ConnectNamedPipe (). The named pipe handle + // must be disconnected from this fleeting client before it + // can be reconnected to new client. + + if (attempts > MAX_ACCEPT_ATTEMPTS) + return -1; + else if (::DisconnectNamedPipe (this->get_handle ()) != 0) + return -1; + // Loop and make another connection attempt. + } + else if (error == ERROR_PIPE_CONNECTED) + // A client connected in the interval between the creation of + // the named pipe instance and the call to ::ConnectNamedPipe + // (). However, the connection is alright. + break; + else // Unrecoverable connection failure, so let's bail out... + return -1; + } + + new_io.set_handle (this->get_handle ()); + new_io.local_addr_ = this->local_addr_; + + // Create a new instance of the pipe for the next connection. + return this->create_new_instance (); +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} diff --git a/ace/SPIPE_Acceptor.h b/ace/SPIPE_Acceptor.h new file mode 100644 index 00000000000..a5d45aa3b42 --- /dev/null +++ b/ace/SPIPE_Acceptor.h @@ -0,0 +1,78 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SPIPE_Acceptor.h +// +// = AUTHOR +// Doug Schmidt and Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_SPIPE_ACCEPTOR_H) +#define ACE_SPIPE_ACCEPTOR_H + +#include "ace/SPIPE_Stream.h" + +class ACE_Export ACE_SPIPE_Acceptor : public ACE_SPIPE + // = TITLE + // Defines the format and interface for the listener side of the + // ACE_SPIPE_Stream. +{ +public: +#if defined (ACE_WIN32) + // = Maximum number of attempts to accept a connection + enum + { + MAX_PIPE_INSTANCES = PIPE_UNLIMITED_INSTANCES, + MAX_ACCEPT_ATTEMPTS = 3 + }; +#endif + + // = Initialization and termination methods. + ACE_SPIPE_Acceptor (void); + // Default constructor. + + ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap, + int reuse_addr = 1, + int perms = ACE_DEFAULT_PERMS); + // Initiate a passive-mode STREAM pipe listener. + + int open (const ACE_SPIPE_Addr &local_sap, + int reuse_addr = 1, + int perms = ACE_DEFAULT_PERMS); + // Initiate a passive-mode STREAM pipe listener. + + int close (void); + // Close down the passive-mode STREAM pipe listener. + + int remove (void); + // Remove the underlying mounted pipe from the file system. + + // = Passive connection acceptance method. + int accept (ACE_SPIPE_Stream &ipc_sap_spipe, + ACE_SPIPE_Addr *remote_addr = 0, + ACE_Time_Value *timeout = 0, + int restart = 1); + // Accept a new data transfer connection. A <timeout> of 0 means + // block forever, a <timeout> of {0, 0} means poll. <restart> == 1 + // means "restart if interrupted." + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +private: + + int create_new_instance (int perms = 0); + // Create a new instance of an SPIPE. +}; + +#endif /* ACE_SPIPE_ACCEPTOR_H */ diff --git a/ace/SPIPE_Acceptor.i b/ace/SPIPE_Acceptor.i new file mode 100644 index 00000000000..441ff5a6232 --- /dev/null +++ b/ace/SPIPE_Acceptor.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// SPIPE_Acceptor.i diff --git a/ace/SPIPE_Addr.cpp b/ace/SPIPE_Addr.cpp new file mode 100644 index 00000000000..09bbc573c7a --- /dev/null +++ b/ace/SPIPE_Addr.cpp @@ -0,0 +1,110 @@ +// SPIPE_Addr.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SPIPE_Addr.h" + +#if !defined (__ACE_INLINE__) +#include "ace/SPIPE_Addr.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Addr) + +void +ACE_SPIPE_Addr::dump (void) const +{ +} + +// Set a pointer to the address. +void +ACE_SPIPE_Addr::set_addr (void *addr, int len) +{ + ACE_TRACE ("ACE_SPIPE_Addr::set_addr"); + + this->ACE_Addr::base_set (AF_SPIPE, len); + ACE_OS::memcpy ((void *) &this->SPIPE_addr_, + (void *) addr, + len); +} + +// Do nothing constructor. + +ACE_SPIPE_Addr::ACE_SPIPE_Addr (void) + : ACE_Addr (AF_SPIPE, sizeof this->SPIPE_addr_) +{ + (void) ACE_OS::memset ((void *) &this->SPIPE_addr_, 0, + sizeof this->SPIPE_addr_); +} + +// Transform the string into the current addressing format. + +int +ACE_SPIPE_Addr::string_to_addr (LPCTSTR addr) +{ + return this->set (addr); +} + +/* Copy constructor. */ + +ACE_SPIPE_Addr::ACE_SPIPE_Addr (const ACE_SPIPE_Addr &sa) + : ACE_Addr (AF_SPIPE, + sizeof this->SPIPE_addr_.gid_ + sizeof this->SPIPE_addr_.uid_ + + ACE_OS::strlen (this->SPIPE_addr_.rendezvous_) + 1) +{ + (void) ACE_OS::memcpy ((void *) &this->SPIPE_addr_, (void *) + &sa.SPIPE_addr_, sa.get_size ()); +} + +int +ACE_SPIPE_Addr::set (LPCTSTR addr, + gid_t gid, + uid_t uid) +{ + int len = sizeof (this->SPIPE_addr_.uid_); + len += sizeof(this->SPIPE_addr_.gid_); + +#if defined (ACE_WIN32) + char *colonp = ACE_OS::strchr (addr, ':'); + char temp[BUFSIZ] ; + + if (colonp == 0) // Assume it's a port number. + { + ACE_OS::strcpy(temp, "\\\\.\\pipe\\") ; + ACE_OS::strcat(temp, addr) ; + } + else + { + ACE_OS::strcpy(temp, "\\\\") ; + *colonp = '\0'; + if (ACE_OS::strcmp(addr, "localhost") == 0) + ACE_OS::strcat(temp, ".") ; // change localhost to . + else + ACE_OS::strcat(temp, addr) ; + ACE_OS::strcat(temp, "\\pipe\\" ) ; + ACE_OS::strcat(temp, colonp+1) ; + } + + this->ACE_Addr::base_set (AF_SPIPE, + ACE_OS::strlen (temp) + len); + ACE_OS::strcpy(this->SPIPE_addr_.rendezvous_, temp) ; + +#else + this->ACE_Addr::base_set (AF_SPIPE, ACE_OS::strlen (addr) + len); + ACE_OS::strncpy (this->SPIPE_addr_.rendezvous_, addr, + sizeof this->SPIPE_addr_.rendezvous_); +#endif + + this->SPIPE_addr_.gid_ = gid == 0 ? ACE_OS::getgid () : gid; + this->SPIPE_addr_.uid_ = uid == 0 ? ACE_OS::getuid () : uid; + return 0; +} + +// Create a ACE_Addr from a ACE_SPIPE pathname. + +ACE_SPIPE_Addr::ACE_SPIPE_Addr (LPCTSTR addr, + gid_t gid, + uid_t uid) +{ + this->set (addr, gid, uid); +} + diff --git a/ace/SPIPE_Addr.h b/ace/SPIPE_Addr.h new file mode 100644 index 00000000000..142e754c322 --- /dev/null +++ b/ace/SPIPE_Addr.h @@ -0,0 +1,101 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SPIPE_Addr.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SPIPE_ADDR_H) +#define ACE_SPIPE_ADDR_H +#include "ace/Addr.h" +#include "ace/ACE.h" + +class ACE_Export ACE_SPIPE_Addr : public ACE_Addr + // = TITLE + // Defines the SVR4 STREAM pipe address family address format. +{ +public: + // = Initialization methods. + ACE_SPIPE_Addr (void); + // Default constructor. + + ACE_SPIPE_Addr (const ACE_SPIPE_Addr &sa); + // Copy constructor. + + ACE_SPIPE_Addr (LPCTSTR rendezvous_point, gid_t = 0, uid_t = 0); + // Create a ACE_SPIPE_Addr from a rendezvous point in the file system. + + int set (LPCTSTR rendezvous_point, gid_t = 0, uid_t = 0); + // Create a ACE_SPIPE_Addr from a rendezvous point in the file system. + + virtual void *get_addr (void) const; + // Return a pointer to the address. + + virtual void set_addr (void *addr, int len); + // Set a pointer to the underlying network address. + + virtual int addr_to_string (char addr[], size_t) const; + // Transform the current address into string format. + + virtual int string_to_addr (LPCTSTR addr); + // Transform the string into the current addressing format. + + // = Equality/inequality tests + virtual int operator == (const ACE_Addr &SAP) const; + // Check for equality. + + virtual int operator != (const ACE_Addr &SAP) const; + // Check for inequality + + // = SPIPE-specific address operations + LPCTSTR get_path_name (void) const; + // Pathname of rendezvous point in file system. + + uid_t user_id (void) const; + // Get user id. + void user_id (uid_t uid); + // Set user id. + + void group_id (gid_t gid); + // Set group ids. + gid_t group_id (void) const; + // Get group ids. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + // = This struct contains security attributes. + struct + { + gid_t gid_; + // Group id. + + uid_t uid_; + // User id. + + TCHAR rendezvous_[MAXNAMLEN + 1]; + // Pathname in the file system. + + } SPIPE_addr_; + // Contents of an SPIPE address. +}; + +#if defined (__ACE_INLINE__) +#include "ace/SPIPE_Addr.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SPIPE_ADDR_H */ diff --git a/ace/SPIPE_Addr.i b/ace/SPIPE_Addr.i new file mode 100644 index 00000000000..358fbc29cfd --- /dev/null +++ b/ace/SPIPE_Addr.i @@ -0,0 +1,70 @@ +/* -*- C++ -*- */ +// $Id$ + +// SPIPE_Addr.i + +// Transform the current address into string format. + +ACE_INLINE int +ACE_SPIPE_Addr::addr_to_string (char s[], size_t len) const +{ + ACE_OS::strncpy (s, this->SPIPE_addr_.rendezvous_, len); + return 0; +} + +// Return the address. + +ACE_INLINE void * +ACE_SPIPE_Addr::get_addr (void) const +{ + return (void *) &this->SPIPE_addr_; +} + +// Compare two addresses for equality. + +ACE_INLINE int +ACE_SPIPE_Addr::operator == (const ACE_Addr &sap) const +{ + return ACE_OS::strcmp (this->SPIPE_addr_.rendezvous_, + ((ACE_SPIPE_Addr &) sap).SPIPE_addr_.rendezvous_) == 0; +} + +// Compare two addresses for inequality. + +ACE_INLINE int +ACE_SPIPE_Addr::operator != (const ACE_Addr &sap) const +{ + return !((*this) == sap); // This is lazy, of course... ;-) +} + +// Return the path name used for the rendezvous point. + +ACE_INLINE LPCTSTR +ACE_SPIPE_Addr::get_path_name (void) const +{ + return this->SPIPE_addr_.rendezvous_; +} + +ACE_INLINE uid_t +ACE_SPIPE_Addr::user_id (void) const +{ + return this->SPIPE_addr_.uid_; +} + +ACE_INLINE void +ACE_SPIPE_Addr::user_id (uid_t uid) +{ + this->SPIPE_addr_.uid_ = uid; +} + +ACE_INLINE gid_t +ACE_SPIPE_Addr::group_id (void) const +{ + return this->SPIPE_addr_.gid_; +} + +ACE_INLINE void +ACE_SPIPE_Addr::group_id (gid_t gid) +{ + this->SPIPE_addr_.gid_ = gid; +} diff --git a/ace/SPIPE_Connector.cpp b/ace/SPIPE_Connector.cpp new file mode 100644 index 00000000000..5d8a7e34f5f --- /dev/null +++ b/ace/SPIPE_Connector.cpp @@ -0,0 +1,68 @@ +// SPIPE_Connector.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SPIPE_Connector.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Connector) + +// Creates a Local ACE_SPIPE. + +ACE_SPIPE_Connector::ACE_SPIPE_Connector (ACE_SPIPE_Stream &new_io, + const ACE_SPIPE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_SPIPE_Connector::ACE_SPIPE_Connector"); + if (this->connect (new_io, remote_sap, timeout, local_sap, + reuse_addr, flags, perms) == -1 + && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + ACE_ERROR ((LM_ERROR, "address %s, %p\n", + remote_sap.get_path_name (), "ACE_SPIPE_Connector")); +} + +void +ACE_SPIPE_Connector::dump (void) const +{ + ACE_TRACE ("ACE_SPIPE_Connector::dump"); +} + +ACE_SPIPE_Connector::ACE_SPIPE_Connector (void) +{ + ACE_TRACE ("ACE_SPIPE_Connector::ACE_SPIPE_Connector"); +} + +int +ACE_SPIPE_Connector::connect (ACE_SPIPE_Stream &new_io, + const ACE_SPIPE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_SPIPE_Connector::connect"); + + // Make darn sure that the O_CREAT flag is not set! + ACE_CLR_BITS (flags, O_CREAT); + ACE_HANDLE handle = ACE::handle_timed_open (timeout, + remote_sap.get_path_name (), + flags, perms); + new_io.set_handle (handle); + new_io.remote_addr_ = remote_sap; // class copy. + +#if defined (ACE_WIN32) + DWORD pipe_mode = PIPE_READMODE_MESSAGE | PIPE_WAIT; + + // Set named pipe mode and buffering characteristics. + if (handle != ACE_INVALID_HANDLE) + return ::SetNamedPipeHandleState (handle, + &pipe_mode, + NULL, + NULL); +#endif + return handle == ACE_INVALID_HANDLE ? -1 : 0; +} diff --git a/ace/SPIPE_Connector.h b/ace/SPIPE_Connector.h new file mode 100644 index 00000000000..bc659f9ae8e --- /dev/null +++ b/ace/SPIPE_Connector.h @@ -0,0 +1,88 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SPIPE_Connector.h +// +// = AUTHOR +// Doug Schmidt and Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_SPIPE_CONNECTOR_H) +#define ACE_SPIPE_CONNECTOR_H + +#include "ace/SPIPE_Stream.h" + +class ACE_Export ACE_SPIPE_Connector : public ACE_SPIPE + // = TITLE + // Defines an active connection factory for the STREAM pipe + // wrappers. +{ +public: + // = Initialization method. + ACE_SPIPE_Connector (void); + // Default constructor. + + ACE_SPIPE_Connector (ACE_SPIPE_Stream &new_io, + const ACE_SPIPE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + int connect (ACE_SPIPE_Stream &new_io, + const ACE_SPIPE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/SPIPE_Connector.i" + +#endif /* ACE_SPIPE_CONNECTOR_H */ diff --git a/ace/SPIPE_Connector.i b/ace/SPIPE_Connector.i new file mode 100644 index 00000000000..cdbc69f06b2 --- /dev/null +++ b/ace/SPIPE_Connector.i @@ -0,0 +1,7 @@ +/* -*- C++ -*- */ +// $Id$ + +// SPIPE_Connector.i + +#include "ace/Log_Msg.h" + diff --git a/ace/SPIPE_Stream.cpp b/ace/SPIPE_Stream.cpp new file mode 100644 index 00000000000..ab38d87e666 --- /dev/null +++ b/ace/SPIPE_Stream.cpp @@ -0,0 +1,93 @@ +// SPIPE_Stream.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SPIPE_Stream.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SPIPE_Stream) + +void +ACE_SPIPE_Stream::dump (void) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::dump"); +} + +// Simple-minded do nothing constructor. + +ACE_SPIPE_Stream::ACE_SPIPE_Stream (void) +{ + ACE_TRACE ("ACE_SPIPE_Stream::ACE_SPIPE_Stream"); +} + +// Send N char *ptrs and int lengths. Note that the char *'s precede +// the ints (basically, an varargs version of writev). The count N is +// the *total* number of trailing arguments, *not* a couple of the +// number of tuple pairs! + +ssize_t +ACE_SPIPE_Stream::send (size_t n, ...) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send"); + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::writev (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + +// This is basically an interface to ACE_OS::readv, that doesn't use +// the struct iovec explicitly. The ... can be passed as an arbitrary +// number of (char *ptr, int len) tuples. However, the count N is the +// *total* number of trailing arguments, *not* a couple of the number +// of tuple pairs! + +ssize_t +ACE_SPIPE_Stream::recv (size_t n, ...) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv"); + va_list argp; + size_t total_tuples = n / 2; + ssize_t result; +#if defined (ACE_HAS_ALLOCA) + iovec *iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + iovec *iovp; + + ACE_NEW_RETURN (iovp, iovec[total_tuples], -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, int); + } + + result = ACE_OS::readv (this->get_handle (), iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} diff --git a/ace/SPIPE_Stream.h b/ace/SPIPE_Stream.h new file mode 100644 index 00000000000..5b78bd1e148 --- /dev/null +++ b/ace/SPIPE_Stream.h @@ -0,0 +1,117 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SPIPE_Stream.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SPIPE_STREAM_H) +#define ACE_SPIPE_STREAM_H + +#include "ace/SPIPE.h" +#include "ace/SPIPE_Addr.h" + +class ACE_Export ACE_SPIPE_Stream : public ACE_SPIPE + // = TITLE + // Define an ACE_SPIPE_Stream. +{ +friend class ACE_SPIPE_Acceptor; +friend class ACE_SPIPE_Connector; +public: + // = Initialization method. + ACE_SPIPE_Stream (void); + // Default constructor. + + int get_remote_addr (ACE_SPIPE_Addr &remote_sap) const; + // Obtain the address of whom we are connected with. + + int send_handle (ACE_HANDLE handle) const; + // Send an open FD to another process. + + int recv_handle (ACE_HANDLE &handle) const; + // Recv an open FD from another process. + + int recv_handle (strrecvfd &recvfd) const; + // Recv an open FD from another process. + + ssize_t send_n (const void *buf, size_t n) const; + // Send n bytes, keep trying until n are sent. + + ssize_t recv_n (void *buf, size_t n) const; + // Recv n bytes, keep trying until n are received. + + ssize_t send (const void *buf, size_t n) const; + // Send bytes via STREAM pipes using "band" mode. + + ssize_t recv (void *buf, size_t n) const; + // Recv bytes via STREAM pipes using "band" mode. + + ssize_t send (const ACE_Str_Buf *cntl, + const ACE_Str_Buf *data, + int flags = 0) const; + // Send <cntl> and <data> via STREAM pipes. + + ssize_t recv (ACE_Str_Buf *cntl, + ACE_Str_Buf *data, + int *flags) const; + // Recv <cntl> and <data> via STREAM pipes. + + ssize_t send (const ACE_Str_Buf *cntl, + const ACE_Str_Buf *data, + int band, + int flags = 0) const; + // Send bytes via STREAM pipes using "band" mode. + + ssize_t recv (ACE_Str_Buf *cntl, + ACE_Str_Buf *data, + int *band, + int *flags) const; + // Recv bytes via STREAM pipes using "band" mode. + + ssize_t send (const iovec iov[], size_t n) const; + // Send iovecs via <::writev>. + + ssize_t recv (iovec iov[], size_t n) const; + // Recv iovecs via <::readv>. + + ssize_t send (size_t n, ...) const; + // Send N char *ptrs and int lengths. Note that the char *'s + // precede the ints (basically, an varargs version of writev). The + // count N is the *total* number of trailing arguments, *not* a + // couple of the number of tuple pairs! + + ssize_t recv (size_t n, ...) const; + // This is an interface to ::readv, that doesn't use the struct + // iovec explicitly. The ... can be passed as an arbitrary number + // of (char *ptr, int len) tuples. However, the count N is the + // *total* number of trailing arguments, *not* a couple of the + // number of tuple pairs! + + ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Send <n> bytes via Win32 WriteFile using overlapped I/O. + + ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; + // Recv <n> bytes via Win32 ReadFile using overlapped I/O. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_SPIPE_Addr remote_addr_; +}; + +#include "ace/SPIPE_Stream.i" +#endif /* ACE_SPIPE_STREAM_H */ diff --git a/ace/SPIPE_Stream.i b/ace/SPIPE_Stream.i new file mode 100644 index 00000000000..7018068e8d7 --- /dev/null +++ b/ace/SPIPE_Stream.i @@ -0,0 +1,160 @@ +/* -*- C++ -*- */ +// $Id$ + +// SPIPE_Stream.i + +// Create an ACE_SPIPE_Stream. + +inline int +ACE_SPIPE_Stream::get_remote_addr (ACE_SPIPE_Addr &remote_sap) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::get_remote_addr"); + remote_sap = this->remote_addr_; + return 0; +} + +// Send exactly N bytes from BUF to this socket. Keeping trying until +// this many bytes are sent. + +inline ssize_t +ACE_SPIPE_Stream::send_n (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send_n"); + return ACE::send_n (this->get_handle (), buf, n); +} + +// Receive exactly N bytes from this socket into BUF. Keep trying +// until this many bytes are received. + +inline ssize_t +ACE_SPIPE_Stream::recv_n (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv_n"); + return ACE::recv_n (this->get_handle (), buf, n); +} + +inline ssize_t +ACE_SPIPE_Stream::send (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send"); + return ACE_OS::write (this->get_handle (), (const char *) buf, n); +} + +inline ssize_t +ACE_SPIPE_Stream::recv (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n); +} + +inline ssize_t +ACE_SPIPE_Stream::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int flags) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send"); + return ACE_OS::putmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags); +} + +inline ssize_t +ACE_SPIPE_Stream::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *flags) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv"); + return ACE_OS::getmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, flags); +} + +inline ssize_t +ACE_SPIPE_Stream::send (const ACE_Str_Buf *cntl, const ACE_Str_Buf *data, int band, int flags) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send"); + return ACE_OS::putpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags); +} + +inline ssize_t +ACE_SPIPE_Stream::recv (ACE_Str_Buf *cntl, ACE_Str_Buf *data, int *band, int *flags) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv"); + return ACE_OS::getpmsg (this->get_handle (), (strbuf *) cntl, (strbuf *) data, band, flags); +} + +inline ssize_t +ACE_SPIPE_Stream::send (const iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send"); + return ACE_OS::writev (this->get_handle (), (iovec *) iov, n); +} + +inline ssize_t +ACE_SPIPE_Stream::recv (iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv"); + return ACE_OS::readv (this->get_handle (), (iovec *) iov, n); +} + +// This routine sends an open file descriptor to this socket. + +inline int +ACE_SPIPE_Stream::send_handle (ACE_HANDLE handle) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send_handle"); +#if defined (ACE_HAS_STREAM_PIPES) + return ACE_OS::ioctl (this->get_handle (), I_SENDFD, (void *) handle); +#else + handle = handle; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +// This file receives an open file descriptor from this socket. + +inline int +ACE_SPIPE_Stream::recv_handle (ACE_HANDLE &handle) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv_handle"); +#if defined (ACE_HAS_STREAM_PIPES) + strrecvfd recvfd; + + if (ACE_OS::ioctl (this->get_handle (), I_RECVFD, (void *) &recvfd) == -1) + return -1; + else + { + handle = recvfd.fd; + return 0; + } +#else + handle = handle; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +// This file receives an open file descriptor from this socket and +// also passes back the information about the address... + +inline int +ACE_SPIPE_Stream::recv_handle (strrecvfd &recvfd) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv_handle"); +#if defined (ACE_HAS_STREAM_PIPES) + return ACE_OS::ioctl (this->get_handle (), I_RECVFD, (void *) &recvfd); +#else + recvfd = recvfd; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +inline ssize_t +ACE_SPIPE_Stream::send (const void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::send"); + return ACE_OS::write (this->get_handle (), + (const char *) buf, n, + overlapped); +} + +inline ssize_t +ACE_SPIPE_Stream::recv (void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const +{ + ACE_TRACE ("ACE_SPIPE_Stream::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n, + overlapped); +} diff --git a/ace/SString.cpp b/ace/SString.cpp new file mode 100644 index 00000000000..82889f8fa7a --- /dev/null +++ b/ace/SString.cpp @@ -0,0 +1,596 @@ +// SString.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Malloc.h" +#include "ace/Service_Config.h" +#include "ace/SString.h" + +#if !defined (__ACE_INLINE__) +#include "ace/SString.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_CString) + +// Copy constructor. + +ACE_CString::ACE_CString (const ACE_CString &s) + : len_ (s.len_), + allocator_ (s.allocator_) + +{ + ACE_TRACE ("ACE_CString::ACE_CString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + this->rep_ = (char *) this->allocator_->malloc (s.len_ + 1); + ACE_OS::memcpy ((void *) this->rep_, (const void *) s.rep_, this->len_); + this->rep_[this->len_] = 0; +} + +void +ACE_CString::dump (void) const +{ + ACE_TRACE ("ACE_CString::dump"); +} + +ACE_CString::~ACE_CString (void) +{ + ACE_TRACE ("ACE_CString::~ACE_CString"); + this->allocator_->free (this->rep_); +} + +size_t +ACE_CString::length (void) const +{ + ACE_TRACE ("ACE_CString::length"); + return this->len_; +} + +// Default constructor. + +ACE_CString::ACE_CString (ACE_Allocator *allocator) + : len_ (0), rep_ (0), + allocator_ (allocator) +{ + ACE_TRACE ("ACE_CString::ACE_CString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); +} + +// Constructor that actually copies memory. + +ACE_CString::ACE_CString (const char *s, ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_CString::ACE_CString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = ACE_OS::strlen (s); + this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1); + ACE_OS::strcpy (this->rep_, s); + } +} + +// Constructor that actually copies memory. + +ACE_CString::ACE_CString (const char *s, + size_t len, + ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_CString::ACE_CString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = len; + this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1); + ACE_OS::strncpy (this->rep_, s, len); + this->rep_[len] = '\0'; // Make sure to NUL terminate this! + } +} + +// Assignment operator (does copy memory). + +void +ACE_CString::operator = (const ACE_CString &s) +{ + ACE_TRACE ("ACE_CString::operator ="); + // Check for identify. + + if (this != &s) + { + // Only reallocate if we don't have enough space... + if (this->len_ < s.len_) + { + this->allocator_->free (this->rep_); + this->rep_ = (char *) this->allocator_->malloc (s.len_ + 1); + } + this->len_ = s.len_; + ACE_OS::strcpy (this->rep_, s.rep_); + } +} + +int +ACE_CString::strstr (const ACE_CString &s) const +{ + ACE_TRACE ("ACE_CString::strstr"); + + if (this->len_ < s.len_) + // If they're larger than we are they can't be a substring of us! + return -1; + else if (this->len_ == s.len_) + // Check if we're equal. + return *this == s ? 0 : -1; + else + { + // They're smaller than we are... + size_t len = this->len_ - s.len_; + + for (size_t i = 0; i < len; i++) + { + size_t j; + + for (j = 0; j < s.len_; j++) + if (this->rep_[i + j] != s.rep_[j]) + break; + + if (j == s.len_) + // Found a match! Return the index. + return i; + } + + return -1; + } +} + +// Concat operator (does copy memory). + +void +ACE_CString::operator += (const ACE_CString &s) +{ + ACE_TRACE ("ACE_CString::operator +="); + + char *t = (char *) this->allocator_->malloc (this->len_ + s.len_ + 1); + ACE_OS::memcpy (t, this->rep_, this->len_); + ACE_OS::memcpy (t + this->len_, s.rep_, s.len_); + this->len_ += s.len_; + t[this->len_] = '\0'; + this->allocator_->free (this->rep_); + this->rep_ = t; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_SString) + +void +ACE_SString::dump (void) const +{ + ACE_TRACE ("ACE_SString::dump"); +} + +size_t +ACE_SString::length (void) const +{ + ACE_TRACE ("ACE_SString::length"); + return this->len_; +} + +// Copy constructor. + +ACE_SString::ACE_SString (const ACE_SString &s) + : len_ (s.len_), + allocator_ (s.allocator_) +{ + ACE_TRACE ("ACE_SString::ACE_SString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + this->rep_ = (char *) this->allocator_->malloc (s.len_ + 1); + ACE_OS::memcpy ((void *) this->rep_, (const void *) s.rep_, this->len_); + this->rep_[this->len_] = 0; +} + +// Default constructor. + +ACE_SString::ACE_SString (ACE_Allocator *allocator) + : allocator_ (allocator), + len_ (0), rep_ (0) +{ + ACE_TRACE ("ACE_SString::ACE_SString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); +} + +int +ACE_SString::strstr (const ACE_SString &s) const +{ + ACE_TRACE ("ACE_SString::strstr"); + + if (this->len_ < s.len_) + // If they're larger than we are they can't be a substring of us! + return -1; + else if (this->len_ == s.len_) + // Check if we're equal. + return *this == s ? 0 : -1; + else + { + // They're smaller than we are... + size_t len = this->len_ - s.len_; + + for (size_t i = 0; i < len; i++) + { + size_t j; + + for (j = 0; j < s.len_; j++) + { + if (this->rep_[i + j] != s.rep_[j]) + break; + } + + if (j == s.len_) + // Found a match! Return the index. + return i; + } + + return -1; + } +} + +// Set the underlying pointer (does not copy memory). + +void +ACE_SString::rep (char *s) +{ + ACE_TRACE ("ACE_SString::rep"); + + this->rep_ = s; + + if (s == 0) + this->len_ = 0; + else + this->len_ = ACE_OS::strlen (s); +} + +// Constructor that actually copies memory. + +ACE_SString::ACE_SString (const char *s, + ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_SString::ACE_SString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = ACE_OS::strlen (s); + this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1); + ACE_OS::strcpy (this->rep_, s); + } +} + +// Constructor that actually copies memory. + +ACE_SString::ACE_SString (const char *s, + size_t len, + ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_SString::ACE_SString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = len; + this->rep_ = (char *) this->allocator_->malloc (this->len_ + 1); + ACE_OS::strncpy (this->rep_, s, len); + this->rep_[len] = '\0'; // Make sure to NUL terminate this! + } +} + +// Assignment operator (does copy memory). + +void +ACE_SString::operator = (const ACE_SString &s) +{ + ACE_TRACE ("ACE_SString::operator ="); + // Check for identify. + + if (this != &s) + { + // Only reallocate if we don't have enough space... + if (this->len_ < s.len_) + { + this->allocator_->free (this->rep_); + this->rep_ = (char *) this->allocator_->malloc (s.len_ + 1); + } + this->len_ = s.len_; + ACE_OS::strcpy (this->rep_, s.rep_); + } +} + +ACE_ALLOC_HOOK_DEFINE(ACE_WString) + +void +ACE_WString::dump (void) const +{ + ACE_TRACE ("ACE_WString::dump"); +} + +// Default constructor. + +ACE_WString::ACE_WString (ACE_Allocator *allocator) + : len_ (0), + rep_ (0), + allocator_ (allocator) +{ + ACE_TRACE ("ACE_WString::ACE_WString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); +} + +size_t +ACE_WString::wstrlen (const ACE_USHORT16 *s) +{ + ACE_TRACE ("ACE_WString::wstrlen"); + int i; + + for (i = 0; s[i] != 0; i++) + continue; + + return i; +} + +// Get the underlying pointer as an ASCII char. + +char * +ACE_WString::char_rep (void) const +{ + ACE_TRACE ("ACE_WString::char_rep"); + if (this->len_ <= 0) + return 0; + else + { + char *t; + + ACE_NEW_RETURN (t, char[this->len_ + 1], 0); + + for (size_t i = 0; i < this->len_; i++) + // Note that this cast may lose data if wide chars are + // actually used! + t[i] = char (this->rep_[i]); + + t[this->len_] = '\0'; + return t; + } +} + +// Constructor that actually copies memory. + +ACE_WString::ACE_WString (const char *s, + ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_WString::ACE_WString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = ACE_OS::strlen (s); + this->rep_ = (ACE_USHORT16 *) this->allocator_->malloc ((this->len_ + 1) * sizeof (ACE_USHORT16)); + + // Copy the char * string byte-by-byte into the ACE_USHORT16 * + // string. + for (size_t i = 0; i < this->len_; i++) + this->rep_[i] = s[i]; + + // null terminate + this->rep_[this->len_] = 0; + } +} + +// Constructor that actually copies memory. + +ACE_WString::ACE_WString (const ACE_USHORT16 *s, ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_WString::ACE_WString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = this->wstrlen (s); + this->rep_ = (ACE_USHORT16 *) this->allocator_->malloc ((this->len_ + 1) * sizeof (ACE_USHORT16)); + + ACE_OS::memcpy (this->rep_, s, this->len_ * sizeof (ACE_USHORT16)); + + // null terminate + this->rep_[this->len_] = 0; + } +} + +// Constructor that actually copies memory. + +ACE_WString::ACE_WString (const ACE_USHORT16 *s, + size_t len, + ACE_Allocator *allocator) + : allocator_ (allocator) +{ + ACE_TRACE ("ACE_WString::ACE_WString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + if (s == 0) + { + this->len_ = 0; + this->rep_ = 0; + } + else + { + this->len_ = len; + this->rep_ = (ACE_USHORT16 *) this->allocator_->malloc ((this->len_ + 1) * sizeof (ACE_USHORT16)); + + ACE_OS::memcpy (this->rep_, s, len * sizeof (ACE_USHORT16)); + + // null terminate + this->rep_[this->len_] = 0; + } +} + +size_t +ACE_WString::length (void) const +{ + ACE_TRACE ("ACE_WString::length"); + return this->len_; +} + +// Copy constructor. + +ACE_WString::ACE_WString (const ACE_WString &s) +: len_ (s.len_), + allocator_ (s.allocator_) +{ + ACE_TRACE ("ACE_WString::ACE_WString"); + + if (this->allocator_ == 0) + this->allocator_ = ACE_Service_Config::allocator (); + + this->rep_ = (ACE_USHORT16 *) this->allocator_->malloc ((s.len_ + 1) * sizeof (ACE_USHORT16)); + ACE_OS::memcpy ((void *) this->rep_, (const void *) s.rep_, + this->len_ * sizeof (ACE_USHORT16)); + this->rep_[this->len_] = 0; +} + +// Assignment operator (does copy memory). + +void +ACE_WString::operator = (const ACE_WString &s) +{ + ACE_TRACE ("ACE_WString::operator ="); + // Check for identify. + + if (this != &s) + { + // Only reallocate if we don't have enough space... + if (this->len_ < s.len_) + { + this->allocator_->free (this->rep_); + this->rep_ = (ACE_USHORT16 *) this->allocator_->malloc ((s.len_ + 1) * sizeof (ACE_USHORT16)); + // null terminate + this->rep_[s.len_] = 0; + } + + this->len_ = s.len_; + ACE_OS::memcpy ((void *) this->rep_, (const void *) s.rep_, + this->len_ * sizeof (ACE_USHORT16)); + } +} + +// Concat operator (does copy memory). + +void +ACE_WString::operator += (const ACE_WString &s) +{ + ACE_TRACE ("ACE_WString::operator +="); + ACE_USHORT16 *t = (ACE_USHORT16 *) this->allocator_->malloc ((this->len_ + s.len_ + 1) * sizeof (ACE_USHORT16)); + + ACE_OS::memcpy ((void *) t, (const void *) this->rep_, this->len_ * sizeof (ACE_USHORT16)); + ACE_OS::memcpy ((void *) (t + this->len_ * sizeof (ACE_USHORT16)), + (const void *) s.rep_, s.len_ * sizeof (ACE_USHORT16)); + this->len_ += s.len_; + + // null terminate + t[this->len_] = 0; + + this->allocator_->free (this->rep_); + this->rep_ = t; +} + +ACE_WString::~ACE_WString (void) +{ + ACE_TRACE ("ACE_WString::~ACE_WString"); + this->allocator_->free (this->rep_); +} + +int +ACE_WString::strstr (const ACE_WString &s) const +{ + ACE_TRACE ("ACE_WString::strstr"); + + if (this->len_ < s.len_) + // If they're larger than we are they can't be a substring of us! + return -1; + else if (this->len_ == s.len_) + // Check if we're equal. + return *this == s ? 0 : -1; + else + { + // They're smaller than we are... + size_t len = this->len_ - s.len_; + + for (size_t i = 0; i < len; i++) + { + size_t j; + + for (j = 0; j < s.len_; j++) + if (this->rep_[i + j] != s.rep_[j]) + break; + + if (j == s.len_) + // Found a match! Return the index. + return i; + } + + return -1; + } +} diff --git a/ace/SString.h b/ace/SString.h new file mode 100644 index 00000000000..c6e906ec73a --- /dev/null +++ b/ace/SString.h @@ -0,0 +1,265 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SString.h +// +// = AUTHOR +// Douglas C. Schmidt (schmidt@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (ACE_SSTRING_H) +#define ACE_SSTRING_H + +#include "ace/ACE.h" + +// Forward decl. +class ACE_Allocator; + +class ACE_Export ACE_CString + // = TITLE + // A simple "C String" (ACE_CString) class. + // + // = DESCRIPTION + // This is a place holder until all compilers implement the + // ANSI/ISO C++ standard String class. Note that we need to use + // this class since the ACE ACE_Map_Manager requires an object + // that supports the operator== and operator!=. + // This class uses an ACE_Allocator to allocate memory + // The user can make this a persistant class by providing an + // ACE_Allocator with a persistable memory pool +{ +public: + ACE_CString (ACE_Allocator *allocator = 0); + // Default constructor. + + ACE_CString (const char *s, ACE_Allocator *allocator = 0); + // Constructor that copies <s> into dynamically allocated memory. + + ACE_CString (const ACE_CString &); + // Copy constructor. + + ~ACE_CString (void); + // Deletes the memory... + + ACE_CString (const char *s, size_t len, ACE_Allocator *allocator = 0); + // Constructor that copies <len> chars of <s> into dynamically + // allocated memory (will NUL terminate the result). + + void operator= (const ACE_CString &); + // Assignment operator (does copy memory). + + size_t length (void) const; + // Return the length of the string. + + char *rep (void) const; + // Get a copy of the underlying pointer. + + void operator += (const ACE_CString &); + // Concat operator (copies memory). + + int strstr (const ACE_CString &s) const; + // Comparison operator that will match substrings. Returns the + // index of the first location that matches, else -1. + + char operator[] (size_t index) const; + // Return the <index'th> character in the string (doesn't perform + // bounds checking). + + int operator== (const ACE_CString &s) const; + // Comparison operator (must match entire string). + + int operator!= (const ACE_CString &s) const; + // Comparison operator. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Allocator *allocator_; + // Pointer to a memory allocator. + + size_t len_; + // Length of the ACE_CString (not counting the trailing '\0'). + + char *rep_; + // Pointer to data. +}; + +class ACE_Export ACE_SString + // = TITLE + // A very "Simple String" (ACE_SString) class. + // + // = DESCRIPTION + // This is *not* a general-purpose string class. It is only + // intended for use with applications that understand how it + // works. In particular, it has no destructor... Note that we + // need to use this class since the ACE ACE_Map_Manager requires + // an object that supports the operator== and operator!=. + // This class uses an ACE_Allocator to allocate memory + // The user can make this a persistant class by providing an + // ACE_Allocator with a persistable memory pool +{ +public: + ACE_SString (ACE_Allocator *allocator = 0); + // Default constructor. + + ACE_SString (const char *s, ACE_Allocator *allocator = 0); + // Constructor that copies <s> into dynamically allocated memory. + + ACE_SString (const char *s, size_t len, ACE_Allocator *allocator = 0); + // Constructor that copies <len> chars of <s> into dynamically + // allocated memory (will NUL terminate the result). + + ACE_SString (const ACE_SString &); + // Copy constructor. + + void operator= (const ACE_SString &); + // Assignment operator (does copy memory). + + size_t length (void) const; + // Return the length of the string. + + void rep (char *s); + // Set the underlying pointer. Since this does not copy memory or + // delete existing memory use with extreme caution!!! + + char *rep (void) const; + // Get the underlying pointer. + + void operator += (const ACE_SString &); + // Concat operator (does copy memory). + + int strstr (const ACE_SString &s) const; + // Comparison operator that will match substrings. Returns the + // index of the first location that matches, else -1. + + char operator[] (size_t index) const; + // Return the <index'th> character in the string (doesn't perform + // bounds checking). + + int operator== (const ACE_SString &s) const; + // Comparison operator (must match entire string). + + int operator!= (const ACE_SString &s) const; + // Comparison operator. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + + ACE_Allocator *allocator_; + // Pointer to a memory allocator. + + size_t len_; + // Length of the ACE_SString (not counting the trailing '\0'). + + char *rep_; + // Pointer to data. +}; + +class ACE_Export ACE_WString + // = TITLE + // A persistent wide string class. + // + // = DESCRIPTION + // This is *not* a general-purpose string class. It is only + // intended for use with applications that understand how it + // works. Note that we need to use this class since the ACE + // ACE_Map_Manager requires an object that supports the operator== + // and operator!=. + // This class uses an ACE_Allocator to allocate memory + // The user can make this a persistant class by providing an + // ACE_Allocator with a persistable memory pool +{ +public: + ACE_WString (ACE_Allocator *allocator = 0); + // Default constructor. + + ACE_WString (const char *s, ACE_Allocator *allocator = 0); + // Constructor that copies <s> into dynamically allocated memory. + + ACE_WString (const ACE_USHORT16 *s, ACE_Allocator *allocator = 0); + // Constructor that copies <s> into dynamically allocated memory. + + ACE_WString (const ACE_USHORT16 *s, size_t len, ACE_Allocator *allocator = 0); + // Constructor that copies <len> ACE_USHORT16's of <s> into dynamically + // allocated memory (will NUL terminate the result). + + ACE_WString (const ACE_WString &s); + // Copy constructor. + + ~ACE_WString (void); + // Deletes the memory... + + ACE_USHORT16 operator[] (size_t index) const; + // Return the <index'th> character in the string (doesn't perform + // bounds checking). + + void operator= (const ACE_WString &); + // Assignment operator (does copy memory). + + void operator += (const ACE_WString &); + // Concat operator (does copy memory). + + size_t length (void) const; + // Return the length of the string. + + ACE_USHORT16 *rep (void) const; + // Gets a copy of the underlying pointer. + + char *char_rep (void) const; + // Transform into a copy of the ASCII character representation. + + ACE_USHORT16 *fast_rep (void) const; + // Get at the underlying representation directly! + + int strstr (const ACE_WString &s) const; + // Comparison operator that will match substrings. Returns the + // index of the first location that matches, else -1. + + int operator== (const ACE_WString &s) const; + // Comparison operator (must match entire string). + + int operator!= (const ACE_WString &s) const; + // Comparison operator. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Allocator *allocator_; + // Pointer to a memory allocator. + + size_t wstrlen (const ACE_USHORT16 *); + // Computes the length of a "0" terminated ACE_USHORT16 *. + + size_t len_; + // Length of the ACE_WString. + + ACE_USHORT16 *rep_; + // Pointer to data. +}; + +#if defined (__ACE_INLINE__) +#include "ace/SString.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SSTRING_H */ diff --git a/ace/SString.i b/ace/SString.i new file mode 100644 index 00000000000..c628f6d42ec --- /dev/null +++ b/ace/SString.i @@ -0,0 +1,141 @@ +/* -*- C++ -*- */ +// $Id$ + +// SString.i + +// Return the <index'th> character in the string. + +ACE_INLINE char +ACE_CString::operator[] (size_t index) const +{ + ACE_TRACE ("ACE_CString::operator[]"); + return this->rep_[index]; +} + +// Get a copy of the underlying representation. + +ACE_INLINE char * +ACE_CString::rep (void) const +{ + ACE_TRACE ("ACE_CString::rep"); + + char *new_string; + ACE_NEW_RETURN (new_string, char[this->len_ + 1], 0); + ACE_OS::strcpy (new_string, this->rep_); + + return new_string; +} + +// Comparison operator. + +ACE_INLINE int +ACE_CString::operator== (const ACE_CString &s) const +{ + ACE_TRACE ("ACE_CString::operator=="); + return this->len_ == s.len_ + && ACE_OS::strcmp (this->rep_, s.rep_) == 0; +} + +// Comparison operator. + +ACE_INLINE int +ACE_CString::operator!= (const ACE_CString &s) const +{ + ACE_TRACE ("ACE_CString::operator!="); + return !(*this == s); +} + +// Return the <index'th> character in the string. + +ACE_INLINE char +ACE_SString::operator[] (size_t index) const +{ + ACE_TRACE ("ACE_SString::operator[]"); + return this->rep_[index]; +} + +// Get the underlying pointer (does not make a copy, so beware!). + +ACE_INLINE char * +ACE_SString::rep (void) const +{ + ACE_TRACE ("ACE_SString::rep"); + return this->rep_; +} + +// Comparison operator. + +ACE_INLINE int +ACE_SString::operator== (const ACE_SString &s) const +{ + ACE_TRACE ("ACE_SString::operator=="); + return this->len_ == s.len_ + && ACE_OS::strcmp (this->rep_, s.rep_) == 0; +} + +// Comparison operator. + +ACE_INLINE int +ACE_SString::operator!= (const ACE_SString &s) const +{ + ACE_TRACE ("ACE_SString::operator!="); + return !(*this == s); +} + +// Get a copy of the underlying representation. + +ACE_INLINE ACE_USHORT16 * +ACE_WString::rep (void) const +{ + ACE_TRACE ("ACE_WString::rep"); + if (this->len_ <= 0) + return 0; + else + { + ACE_USHORT16 *t; + ACE_NEW_RETURN (t, ACE_USHORT16[this->len_ + 1], 0); + ACE_OS::memcpy (t, this->rep_, this->len_ * sizeof (ACE_USHORT16)); + + // null terminate + t[this->len_] = 0; + + return t; + } +} + +// Get at the underlying representation directly! + +ACE_INLINE ACE_USHORT16 * +ACE_WString::fast_rep (void) const +{ + return this->rep_; +} + +// Comparison operator. + +ACE_INLINE int +ACE_WString::operator== (const ACE_WString &s) const +{ + ACE_TRACE ("ACE_WString::operator=="); + return this->len_ == s.len_ + && ACE_OS::memcmp ((const void *) this->rep_, (const void *) s.rep_, + this->len_ * sizeof (ACE_USHORT16)) == 0; +} + +// Comparison operator. + +ACE_INLINE int +ACE_WString::operator!= (const ACE_WString &s) const +{ + ACE_TRACE ("ACE_WString::operator!="); + return !(*this == s); +} + +// Return the <index'th> character in the string. + +ACE_INLINE ACE_USHORT16 +ACE_WString::operator[] (size_t index) const +{ + ACE_TRACE ("ACE_WString::operator[]"); + return this->rep_[index]; +} diff --git a/ace/SV_Message.cpp b/ace/SV_Message.cpp new file mode 100644 index 00000000000..dc2e8413b18 --- /dev/null +++ b/ace/SV_Message.cpp @@ -0,0 +1,18 @@ +// SV_Message.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SV_Message.h" + +#if !defined (__ACE_INLINE__) +#include "ace/SV_Message.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_SV_Message) + +void +ACE_SV_Message::dump (void) const +{ + ACE_TRACE ("ACE_SV_Message::dump"); +} + diff --git a/ace/SV_Message.h b/ace/SV_Message.h new file mode 100644 index 00000000000..7ee965520ae --- /dev/null +++ b/ace/SV_Message.h @@ -0,0 +1,51 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SV_Message.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SV_MESSAGE_H) +#define ACE_SV_MESSAGE_H + +#include "ace/ACE.h" + +class ACE_Export ACE_SV_Message + // = TITLE + // Defines the header file for the C++ wrapper for message queues. */ +{ +public: + // = Initialization and termination methods. + ACE_SV_Message (long type = 0); + ~ACE_SV_Message (void); + + // = Get/set the message type. + long type (void) const; + void type (long); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + long type_; + // Type of the message. +}; + +#if defined (__ACE_INLINE__) +#include "ace/SV_Message.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SV_MESSAGE_H */ diff --git a/ace/SV_Message.i b/ace/SV_Message.i new file mode 100644 index 00000000000..8c08e41d151 --- /dev/null +++ b/ace/SV_Message.i @@ -0,0 +1,31 @@ +/* -*- C++ -*- */ +// $Id$ + +// SV_Message.i + +ACE_INLINE +ACE_SV_Message::ACE_SV_Message (long t) + : type_ (t) +{ + ACE_TRACE ("ACE_SV_Message::ACE_SV_Message"); +} + +ACE_INLINE +ACE_SV_Message::~ACE_SV_Message (void) +{ + ACE_TRACE ("ACE_SV_Message::~ACE_SV_Message"); +} + +ACE_INLINE long +ACE_SV_Message::type (void) const +{ + ACE_TRACE ("ACE_SV_Message::type"); + return this->type_; +} + +ACE_INLINE void +ACE_SV_Message::type (long t) +{ + ACE_TRACE ("ACE_SV_Message::type"); + this->type_ = t; +} diff --git a/ace/SV_Message_Queue.cpp b/ace/SV_Message_Queue.cpp new file mode 100644 index 00000000000..0350904392b --- /dev/null +++ b/ace/SV_Message_Queue.cpp @@ -0,0 +1,34 @@ +// SV_Message_Queue.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SV_Message_Queue.h" +#include "ace/Log_Msg.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SV_Message_Queue) + +void +ACE_SV_Message_Queue::dump (void) const +{ + ACE_TRACE ("ACE_SV_Message_Queue::dump"); +} + +ACE_SV_Message_Queue::ACE_SV_Message_Queue (void) +{ + ACE_TRACE ("ACE_SV_Message_Queue::ACE_SV_Message_Queue"); +} + +ACE_SV_Message_Queue::~ACE_SV_Message_Queue (void) +{ + ACE_TRACE ("ACE_SV_Message_Queue::~ACE_SV_Message_Queue"); +} + +ACE_SV_Message_Queue::ACE_SV_Message_Queue (key_t external_id, + int create, + int perms) +{ + ACE_TRACE ("ACE_SV_Message_Queue::ACE_SV_Message_Queue"); + if (this->open (external_id, create, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SV_Message_Queue::ACE_SV_Message_Queue")); +} diff --git a/ace/SV_Message_Queue.h b/ace/SV_Message_Queue.h new file mode 100644 index 00000000000..cd9c85f82e8 --- /dev/null +++ b/ace/SV_Message_Queue.h @@ -0,0 +1,86 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SV_Message_Queue.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_MESSAGE_QUEUE_H) +#define ACE_MESSAGE_QUEUE_H + +#include "ace/ACE.h" +#include "ace/SV_Message.h" + +class ACE_Export ACE_SV_Message_Queue + // = TITLE + // Defines the header file for the C++ wrapper for System V IPC + // message queues. +{ +public: + // = Useful symbolic constants. + enum + { + ACE_CREATE = IPC_CREAT, + ACE_OPEN = 0, + ACE_NOWAIT = IPC_NOWAIT + }; + + // = Initialization and termination methods. + ACE_SV_Message_Queue (void); + ACE_SV_Message_Queue (key_t external_id, + int create = ACE_SV_Message_Queue::ACE_OPEN, + int perms = ACE_DEFAULT_PERMS); + int open (key_t external_id, + int create = ACE_SV_Message_Queue::ACE_OPEN, + int perms = ACE_DEFAULT_PERMS); + // Open a message queue using the <external_id>. + + ~ACE_SV_Message_Queue (void); + + int close (void); + // Close down this instance of the message queue without removing it + // from the system. + + int remove (void); + // Close down and remove the message queue from the system. + + + // = Message transfer methods. + int recv (ACE_SV_Message &mb, + int length, + long mtype = 0, + int mflags = 0); + + int send (const ACE_SV_Message &mb, + int length, + int mflags = 0); + + int control (int option, void *arg = 0); + // Access the underlying control operations. + + // = Get/set the underly internal id. + int get_id (void); + void set_id (int); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + int internal_id_; + // Returned from the underlying msgget() system call. +}; + +#include "ace/SV_Message_Queue.i" +#endif /* ACE_MESSAGE_QUEUE_H */ diff --git a/ace/SV_Message_Queue.i b/ace/SV_Message_Queue.i new file mode 100644 index 00000000000..f896388232e --- /dev/null +++ b/ace/SV_Message_Queue.i @@ -0,0 +1,78 @@ +/* -*- C++ -*- */ +// $Id$ + +// SV_Message_Queue.i + +#include "ace/SV_Message_Queue.h" + +// Open a message queue using the <external_id>. + +inline int +ACE_SV_Message_Queue::open (key_t external_id, int create, int perms) +{ + ACE_TRACE ("ACE_SV_Message_Queue::open"); + return this->internal_id_ = ACE_OS::msgget (external_id, create | perms); +} + +// What does it mean to close a message queue?! + +inline int +ACE_SV_Message_Queue::close (void) +{ + ACE_TRACE ("ACE_SV_Message_Queue::close"); + this->internal_id_ = -1; + return 1; +} + +inline int +ACE_SV_Message_Queue::control (int option, void *arg) +{ + ACE_TRACE ("ACE_SV_Message_Queue::control"); + return ACE_OS::msgctl (this->internal_id_, option, + (msqid_ds *) arg); +} + +inline int +ACE_SV_Message_Queue::remove (void) +{ + ACE_TRACE ("ACE_SV_Message_Queue::remove"); + int result = this->control (IPC_RMID); + this->internal_id_ = -1; + return result; +} + +inline int +ACE_SV_Message_Queue::get_id (void) +{ + ACE_TRACE ("ACE_SV_Message_Queue::get_id"); + return this->internal_id_; +} + +inline void +ACE_SV_Message_Queue::set_id (int id) +{ + ACE_TRACE ("ACE_SV_Message_Queue::set_id"); + this->internal_id_ = id; +} + +inline int +ACE_SV_Message_Queue::recv (ACE_SV_Message &mb, + int length, + long type, + int mflags) +{ + ACE_TRACE ("ACE_SV_Message_Queue::recv"); + return ACE_OS::msgrcv (this->internal_id_, (void *) &mb, + length, type, mflags); +} + +inline int +ACE_SV_Message_Queue::send (const ACE_SV_Message &mb, + int length, + int mflags) +{ + ACE_TRACE ("ACE_SV_Message_Queue::send"); + return ACE_OS::msgsnd (this->internal_id_, (void *) &mb, + length, mflags); +} + diff --git a/ace/SV_Semaphore_Complex.cpp b/ace/SV_Semaphore_Complex.cpp new file mode 100644 index 00000000000..1586c7fb8a9 --- /dev/null +++ b/ace/SV_Semaphore_Complex.cpp @@ -0,0 +1,240 @@ +// SV_Semaphore_Complex.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/SV_Semaphore_Complex.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SV_Semaphore_Complex) + +void +ACE_SV_Semaphore_Complex::dump (void) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::dump"); +} + +// initial value of process +const int ACE_SV_Semaphore_Complex::BIGCOUNT_ = 10000; + +// Define the ACE_SV_Semaphore operation arrays for the semop() calls. +sembuf ACE_SV_Semaphore_Complex::op_lock_[2] = +{ + {0, 0, 0}, // Wait for [0] (lock) to equal 0 + {0, 1, SEM_UNDO}, // then increment [0] to 1 - this locks it. + // UNDO to release the lock if processes exit + // before explicitly unlocking. +}; + +sembuf ACE_SV_Semaphore_Complex::op_endcreate_[2] = +{ + {1, -1, SEM_UNDO}, // Decrement [1] (proc counter) with undo on + // exit, UNDO to adjust proc counter if + // process exits before explicitly calling close() + {0, -1, SEM_UNDO}, // the decrement [0] (lock) back to 0 +}; + +sembuf ACE_SV_Semaphore_Complex::op_open_[1] = +{ + {1, -1, SEM_UNDO}, // Decrement [1] (proc counter) with undo on + // exit. +}; + +sembuf ACE_SV_Semaphore_Complex::op_close_[3] = +{ + {0, 0, 0}, // Wait for [0] (lock) to equal 0 + {0, 1, SEM_UNDO}, // then increment [0] to 1 - this lock it + {1, 1, SEM_UNDO}, // then increment [1] (proc counter) +}; + +sembuf ACE_SV_Semaphore_Complex::op_unlock_[1] = +{ + {0, -1, SEM_UNDO}, // Decrement [0] (lock) back to 0 +}; + +// Open or create an array of SV_Semaphores. We return 0 if all is OK, else -1. + +int +ACE_SV_Semaphore_Complex::open (key_t k, + int create, + int initial_value, + int nsems, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::open"); + if (k == IPC_PRIVATE) + return -1; + + this->key_ = k; + + if (create == ACE_SV_Semaphore_Complex::ACE_CREATE) + { + int result; + + do + { + this->internal_id_ = ACE_OS::semget + (this->key_, 2 + nsems, perms | ACE_SV_Semaphore_Complex::ACE_CREATE); + + if (this->internal_id_ == -1) + return -1; // permission problem or tables full + + // When the ACE_SV_Semaphore is created, we know that the + // value of all 3 members is 0. Get a lock on the + // ACE_SV_Semaphore by waiting for [0] to equal 0, then + // increment it. + + // There is a race condition here. There is the possibility + // that between the semget() above and the semop() below, + // another process can call out close() function which can + // remove the ACE_SV_Semaphore if that process is the last + // one using it. Therefor we handle the error condition of + // an invalid ACE_SV_Semaphore ID specifically below, and if + // it does happen, we just go back and create it again. + result = ACE_OS::semop (this->internal_id_, + &ACE_SV_Semaphore_Complex::op_lock_[0], + 2); + } + while (result == -1 && (errno == EINVAL || errno == EIDRM)); + + if (result == -1) + return -1; + + // Get the value of the process counter. If it equals 0, then no + // one has initialized the ACE_SV_Semaphore yet. + + int semval; + + if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) < 0) + return this->init (); + + if (semval == 0) + { + // We should initialize by doing a SETALL, but that would + // clear the adjust value that we set when we locked the + // ACE_SV_Semaphore above. Instead we do system calls to + // initialize [1], as well as all the nsems SV_Semaphores. + + if (ACE_SV_Semaphore_Simple::control (SETVAL, + ACE_SV_Semaphore_Complex::BIGCOUNT_, + 1) == -1) + return -1; + else + for (int i = 0; i < nsems; i++) + if (this->control (SETVAL, initial_value, i) == -1) + return -1; + } + + // Decrement the process counter and then release the lock. + return ACE_OS::semop (this->internal_id_, + &ACE_SV_Semaphore_Complex::op_endcreate_[0], + 2); + } + else + { + this->internal_id_ = ACE_OS::semget (this->key_, 2 + nsems, 0); + if (this->internal_id_ == -1) + return -1; // doesn't exist or tables full + + // Decrement the process counter. We don't need a lock to do this. + if (ACE_OS::semop (this->internal_id_, + &ACE_SV_Semaphore_Complex::op_open_[0], 1) < 0) + return this->init (); + return 0; + } +} + +int +ACE_SV_Semaphore_Complex::open (const char *name, + int flags, + int initial_value, + int nsems, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::open"); + return this->open (ACE_SV_Semaphore_Simple::name_2_key (name), + flags, initial_value, nsems, perms); +} + +// Close a ACE_SV_Semaphore. Unlike the remove above, this function is +// for a process to call before it exits, when it is done with the +// ACE_SV_Semaphore. We "decrement" the counter of processes using the +// ACE_SV_Semaphore, and if this was the last one, we can remove the +// ACE_SV_Semaphore. + +int +ACE_SV_Semaphore_Complex::close (void) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::close"); + int semval; + + if (this->key_ <= (key_t) - 1 || this->internal_id_ == -1) + return -1; + + // The following semop() first gets a lock on the ACE_SV_Semaphore, + // then increments [1] - the process number. + + if (ACE_OS::semop (this->internal_id_, + &ACE_SV_Semaphore_Complex::op_close_[0], + 3) == -1) + return -1; + + // Now that we have a lock, read the value of the process counter to + // see if this is the last reference to the ACE_SV_Semaphore. There + // is a race condition here - see the comments in create (). + + if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) == -1) + return -1; + + if (semval > ACE_SV_Semaphore_Complex::BIGCOUNT_) + return -1; + else if (semval == ACE_SV_Semaphore_Complex::BIGCOUNT_) + return this->remove (); + else + { + int result = ACE_OS::semop (this->internal_id_, + &ACE_SV_Semaphore_Complex::op_unlock_[0], 1); + + this->init (); + + return result; + } +} + +ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (key_t k, + int flags, + int initial_value, + int nsems, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex"); + if (this->open (k, flags, initial_value, nsems, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SV_Semaphore_Complex")); +} + +ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (const char *name, + int flags, + int initial_value, + int nsems, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex"); + if (this->open (ACE_SV_Semaphore_Simple::name_2_key (name), + flags, initial_value, nsems, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SV_Semaphore_Complex")); +} + +ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex (void) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::~ACE_SV_Semaphore_Complex"); + if (this->internal_id_ >= 0) + this->close (); +} + +ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex (void) +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::ACE_SV_Semaphore_Complex"); + this->init (); +} + diff --git a/ace/SV_Semaphore_Complex.h b/ace/SV_Semaphore_Complex.h new file mode 100644 index 00000000000..42cf1480830 --- /dev/null +++ b/ace/SV_Semaphore_Complex.h @@ -0,0 +1,149 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE_SV_Semaphore_Complex.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SV_SEMAPHORE_COMPLEX_H) +#define ACE_SV_SEMAPHORE_COMPLEX_H + +#include "ace/SV_Semaphore_Simple.h" + +class ACE_Export ACE_SV_Semaphore_Complex : private ACE_SV_Semaphore_Simple + // = TITLE + // This is a more complex semaphore wrapper that handles race + // conditions for initialization correctly... + // + // = DESCRIPTION + // This code is a port to C++, inspired by: W. Richard Stevens + // from his book: UNIX Network Programming (Prentice Hall, ISBN + // 0-13-949876-1 - 1990) ACE_SV_Semaphore Interface: we provide + // a simpler and easier to understand interface to the System V + // ACE_SV_Semaphore calls. We create and use a 2 + n-member + // set for the requested ACE_SV_Semaphore. The first member, + // [0], is a counter used to know when all processes have + // finished with the ACE_SV_Semaphore. The counter is + // initialized to a large number, decremented on every create + // or open and incremented on every close. This way we can use + // the "adjust" feature provided by System V so that any + // process that exit's without calling close() is accounted + // for. It doesn't help us if the last process does this (as we + // have no way of getting control to remove the + // ACE_SV_Semaphore) but it will work if any process other than + // the last does an exit (intentional or unintentional). + // + // The second member, [1], of the ACE_SV_Semaphore is used as a + // lock variable to avoid any race conditions in the create() + // and close() functions. + // + // The members beyond [1] are actual ACE_SV_Semaphore values in + // the array of SV_Semaphores (which may be sized by the user + // in the constructor). +{ +public: + enum + { + ACE_CREATE = IPC_CREAT, + ACE_OPEN = 0 + }; + + // = Initialization and termination methods. + ACE_SV_Semaphore_Complex (void); + ACE_SV_Semaphore_Complex (key_t key, + int create = ACE_SV_Semaphore_Complex::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + ACE_SV_Semaphore_Complex (const char *name, + int create = ACE_SV_Semaphore_Complex::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + ~ACE_SV_Semaphore_Complex (void); + + int open (const char *name, + int flags = ACE_SV_Semaphore_Simple::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + // Open or create an array of SV_Semaphores. We return 0 if all is + // OK, else -1. + + int open (key_t key, + int flags = ACE_SV_Semaphore_Simple::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + // Open or create an array of SV_Semaphores. We return 0 if all is + // OK, else -1. + + int close (void); + // Close an ACE_SV_Semaphore. Unlike the <remove> method, this + // method is for a process to call before it exits, when it is done + // with the ACE_SV_Semaphore. We "decrement" the counter of + // processes using the ACE_SV_Semaphore, and if this was the last + // one, we can remove the ACE_SV_Semaphore. + + // = Semaphore acquire and release methods. + + int acquire (int n = 0, int flags = 0) const; + // Acquire the semaphore. + + int acquire_read (int n = 0, int flags = 0) const; + // Acquire a semaphore for reading. + + int acquire_write (int n = 0, int flags = 0) const; + // Acquire a semaphore for writing + + int tryacquire (int n = 0, int flags = 0) const; + // Try to acquire the semaphore. + + int tryacquire_read (int n = 0, int flags = 0) const; + // Try to acquire the semaphore for reading. + + int tryacquire_write (int n = 0, int flags = 0) const; + // Try to acquire the semaphore for writing. + + int release (int n = 0, int flags = 0) const; + // Release the semaphore. + + // = Semaphore operation methods. + int op (int val, int n = 0, int flags = 0) const; + int op (sembuf op_vec[], int n) const; + + // = Semaphore control methods. + int control (int cmd, semun arg, int n = 0) const; + int control (int cmd, int value = 0, int n = 0) const; + + // = Upgrade access control... + ACE_SV_Semaphore_Simple::get_id; + ACE_SV_Semaphore_Simple::remove; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + static const int BIGCOUNT_; + static sembuf op_lock_[2]; + static sembuf op_endcreate_[2]; + static sembuf op_open_[1]; + static sembuf op_close_[3]; + static sembuf op_unlock_[1]; +}; + +#include "ace/SV_Semaphore_Complex.i" +#endif /* ACE_SV_SEMAPHORE_COMPLEX_H */ diff --git a/ace/SV_Semaphore_Complex.i b/ace/SV_Semaphore_Complex.i new file mode 100644 index 00000000000..b85fd09ec6d --- /dev/null +++ b/ace/SV_Semaphore_Complex.i @@ -0,0 +1,83 @@ +/* -*- C++ -*- */ +// $Id$ + +// SV_Semaphore_Complex.i + +#include "ace/Trace.h" + +inline int +ACE_SV_Semaphore_Complex::acquire (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire"); + return ACE_SV_Semaphore_Simple::acquire (n + 2, flags); +} + +inline int +ACE_SV_Semaphore_Complex::acquire_read (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_read"); + return this->acquire (n, flags); +} + +inline int +ACE_SV_Semaphore_Complex::acquire_write (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::acquire_write"); + return this->acquire (n, flags); +} + +inline int +ACE_SV_Semaphore_Complex::tryacquire (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire"); + return ACE_SV_Semaphore_Simple::tryacquire (n + 2, flags); +} + +inline int +ACE_SV_Semaphore_Complex::tryacquire_read (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_read"); + return this->tryacquire (n, flags); +} + +inline int +ACE_SV_Semaphore_Complex::tryacquire_write (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::tryacquire_write"); + return this->tryacquire (n, flags); +} + +inline int +ACE_SV_Semaphore_Complex::release (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::release"); + return ACE_SV_Semaphore_Simple::release (n + 2, flags); +} + +inline int +ACE_SV_Semaphore_Complex::op (int val, int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::op"); + return ACE_SV_Semaphore_Simple::op (val, n + 2, flags); +} + +inline int +ACE_SV_Semaphore_Complex::op (sembuf op_vec[], int n) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::op"); + return ACE_SV_Semaphore_Simple::op (op_vec, n + 2); +} + +inline int +ACE_SV_Semaphore_Complex::control (int cmd, semun arg, int n) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::control"); + return ACE_SV_Semaphore_Simple::control (cmd, arg, n + 2); +} + +inline int +ACE_SV_Semaphore_Complex::control (int cmd, int value, int n) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Complex::control"); + return ACE_SV_Semaphore_Simple::control (cmd, value, n + 2); +} diff --git a/ace/SV_Semaphore_Simple.cpp b/ace/SV_Semaphore_Simple.cpp new file mode 100644 index 00000000000..6ae67ea116d --- /dev/null +++ b/ace/SV_Semaphore_Simple.cpp @@ -0,0 +1,179 @@ +// SV_Semaphore_Simple.cpp +// $Id$ + +/* -*- C++ -*- */ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/SV_Semaphore_Simple.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_SV_Semaphore_Simple) + +void +ACE_SV_Semaphore_Simple::dump (void) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::dump"); +} + +int +ACE_SV_Semaphore_Simple::control (int cmd, + int value, + int semnum) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::control"); + if (this->internal_id_ == -1) + return -1; + else + { + semun semctl_arg; + + semctl_arg.val = value; + return ACE_OS::semctl (this->internal_id_, semnum, + cmd, semctl_arg); + } +} + +int +ACE_SV_Semaphore_Simple::init (key_t k, int i) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::init"); + this->key_ = k; + this->internal_id_ = i; + return 0; +} + +// General ACE_SV_Semaphore operation. Increment or decrement by a +// specific amount (positive or negative; amount can`t be zero). + +int +ACE_SV_Semaphore_Simple::op (int val, int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::op"); + sembuf op_op; + + op_op.sem_num = n; + op_op.sem_flg = flags; + + if (this->internal_id_ == -1) + return -1; + else if ((op_op.sem_op = val) == 0) + return -1; + else + return ACE_OS::semop (this->internal_id_, &op_op, 1); +} + +// Open or create one or more SV_Semaphores. We return 0 if all is +// OK, else -1. + +int +ACE_SV_Semaphore_Simple::open (key_t k, + int flags, + int initial_value, + int n, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::open"); + union semun ivalue; + + if (k == IPC_PRIVATE || k == ACE_INVALID_SEM_KEY) + return -1; + + ivalue.val = initial_value; + this->key_ = k; + this->sem_number_ = n; + + this->internal_id_ = ACE_OS::semget (this->key_, n, perms | flags); + + if (this->internal_id_ == -1) + return -1; + + if (flags == IPC_CREAT) + { + for (int i = 0; i < n; i++) + if (ACE_OS::semctl (this->internal_id_, i, SETVAL, ivalue) == -1) + return -1; + } + + return 0; +} + +ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (key_t k, + int flags, + int initial_value, + int n, + int perms) + : key_ (k) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple"); + if (this->open (k, flags, initial_value, n, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_SV_Semaphore::ACE_SV_Semaphore")); +} + +// Convert name to key. This function is used internally to create keys +// for the semaphores. A valid name contains letters and digits +// only and MUST start with a letter. +// +// The method for generating names is not very sophisticated, so +// caller should not pass strings which match each other for the first +// LUSED characters when he wants to get a different key. + +key_t +ACE_SV_Semaphore_Simple::name_2_key (const char *name) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::name_2_key"); + + if (name == 0 || !isalpha (*name)) + { + errno = EINVAL; + return ACE_INVALID_SEM_KEY; + } + + // The key is the character value of the first LUSED chars from name + // placed in proto. + + u_long proto = 0; + + for (int i = 0; i < LUSED; ++i) + { + if (*name == '\0') + break; + proto <<= 8; + proto |= *name++ & 0xff; + } + + return (key_t) proto; +} + +// Open or create a ACE_SV_Semaphore. We return 1 if all is OK, else +// 0. + +int +ACE_SV_Semaphore_Simple::open (const char *name, + int flags, + int initial_value, + int n, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::open"); + return this->open (this->name_2_key (name), + flags, initial_value, n, perms); +} + +ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (const char *name, + int flags, + int initial_value, + int n, + int perms) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple"); + if (this->open (name, flags, initial_value, n, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple")); +} + +ACE_SV_Semaphore_Simple::~ACE_SV_Semaphore_Simple (void) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::~ACE_SV_Semaphore_Simple"); + this->close (); +} + diff --git a/ace/SV_Semaphore_Simple.h b/ace/SV_Semaphore_Simple.h new file mode 100644 index 00000000000..660c69faf5d --- /dev/null +++ b/ace/SV_Semaphore_Simple.h @@ -0,0 +1,138 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SV_Semaphore_Simple.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SV_SEMAPHORE_SIMPLE_H) +#define ACE_SV_SEMAPHORE_SIMPLE_H + +#include "ace/ACE.h" + +class ACE_Export ACE_SV_Semaphore_Simple + // = TITLE + // This is a simple semaphore package that assumes there are + // no race conditions for initialization (i.e., the order of + // process startup must be well defined). +{ +public: + enum + { + ACE_CREATE = IPC_CREAT, + ACE_OPEN = 0 + }; + + // = Initialization and termination methods. + ACE_SV_Semaphore_Simple (void); + ACE_SV_Semaphore_Simple (key_t key, + int flags = ACE_SV_Semaphore_Simple::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + ACE_SV_Semaphore_Simple (const char *name, + int flags = ACE_SV_Semaphore_Simple::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + ~ACE_SV_Semaphore_Simple (void); + + int open (const char *name, + int flags = ACE_SV_Semaphore_Simple::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + + int open (key_t key, + int flags = ACE_SV_Semaphore_Simple::ACE_CREATE, + int initial_value = 1, + int nsems = 1, + int perms = ACE_DEFAULT_PERMS); + // Open or create one or more SV_Semaphores. We return 0 if all is + // OK, else -1. + + int close (void); + // Close a ACE_SV_Semaphore, marking it as invalid for subsequent + // operations... + + int remove (void) const; + // Remove all SV_Semaphores associated with a particular key. This + // call is intended to be called from a server, for example, when it + // is being shut down, as we do an IPC_RMID on the ACE_SV_Semaphore, + // regardless of whether other processes may be using it or not. + // Most other processes should use close() below. + + // = Semaphore acquire and release methods. + int acquire (int n = 0, int flags = 0) const; + // Wait until a ACE_SV_Semaphore's value is greater than 0, the + // decrement it by 1 and return. Dijkstra's P operation, Tannenbaums + // DOWN operation. + + int acquire_read (int n = 0, int flags = 0) const; + // Acquire a semaphore for reading. + + int acquire_write (int n = 0, int flags = 0) const; + // Acquire a semaphore for writing + + int tryacquire (int n = 0, int flags = 0) const; + // Non-blocking version of <acquire>. + + int tryacquire_read (int n = 0, int flags = 0) const; + // Try to acquire the semaphore for reading. + + int tryacquire_write (int n = 0, int flags = 0) const; + // Try to acquire the semaphore for writing. + + int release (int n = 0, int flags = 0) const; + // Increment ACE_SV_Semaphore by one. Dijkstra's V operation, + // Tannenbaums UP operation. + + // = Semaphore operation methods. + int op (int val, int semnum = 0, int flags = 0) const; + // General ACE_SV_Semaphore operation. Increment or decrement by a + // specific amount (positive or negative; amount can`t be zero). + + int op (sembuf op_vec[], int nsems) const; + // General ACE_SV_Semaphore operation on an array of SV_Semaphores. + + // = Semaphore control methods. + int control (int cmd, semun arg, int semnum = 0) const; + int control (int cmd, int value = 0, int semnum = 0) const; + + int get_id (void) const; + // Get underlying internal id. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + key_t key_; + int internal_id_; + int sem_number_; + + int init (key_t k = ACE_INVALID_SEM_KEY, int i = -1); + key_t name_2_key (const char *name); + // Convert name to key This function is used internally to create + // keys for the semaphores. A valid name contains letters and + // digits only and MUST start with a letter. + // + // The method for generating names is not very sophisticated, so + // caller should not pass strings which match each other for the first + // LUSED characters when he wants to get a different key. +}; + +#include "ace/SV_Semaphore_Simple.i" +#endif /* _SV_SEMAPHORE_SIMPLE_H */ diff --git a/ace/SV_Semaphore_Simple.i b/ace/SV_Semaphore_Simple.i new file mode 100644 index 00000000000..1679dd724c6 --- /dev/null +++ b/ace/SV_Semaphore_Simple.i @@ -0,0 +1,132 @@ +/* -*- C++ -*- */ +// $Id$ + +// SV_Semaphore_Simple.i + +#include "ace/SV_Semaphore_Simple.h" +#include "ace/Trace.h" + +#undef LUSED +#define LUSED 4 // # of chars used from name + +inline int +ACE_SV_Semaphore_Simple::control (int cmd, + semun arg, + int semnum) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::control"); + return this->internal_id_ == -1 ? + -1 : ACE_OS::semctl (this->internal_id_, semnum, cmd, arg); +} + +// Remove all SV_Semaphores associated with a particular key. This +// call is intended to be called from a server, for example, when it +// is being shut down, as we do an IPC_RMID on the ACE_SV_Semaphore, +// regardless of whether other processes may be using it or not. Most +// other processes should use close() below. + +inline int +ACE_SV_Semaphore_Simple::remove (void) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::remove"); + int result = this->control (IPC_RMID); + ((ACE_SV_Semaphore_Simple *) this)->init (); + return result; +} + +// Close a ACE_SV_Semaphore, marking it as invalid for subsequent +// operations... + +inline int +ACE_SV_Semaphore_Simple::close (void) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::close"); + return this->init (); +} + +// General ACE_SV_Semaphore operation on an array of SV_Semaphores. + +inline int +ACE_SV_Semaphore_Simple::op (sembuf op_vec[], int n) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::op"); + return this->internal_id_ == -1 + ? -1 : ACE_OS::semop (this->internal_id_, op_vec, n); +} + +inline +ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple (void) +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::ACE_SV_Semaphore_Simple"); + this->init (); +} + +// Wait until a ACE_SV_Semaphore's value is greater than 0, the +// decrement it by 1 and return. Dijkstra's P operation, Tannenbaums +// DOWN operation. + +inline int +ACE_SV_Semaphore_Simple::acquire (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire"); + return this->op (-1, n, flags); +} + +inline int +ACE_SV_Semaphore_Simple::acquire_read (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire_read"); + return this->acquire (n, flags); +} + +inline int +ACE_SV_Semaphore_Simple::acquire_write (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::acquire_write"); + return this->acquire (n, flags); +} + +// Non-blocking version of acquire(). + +inline int +ACE_SV_Semaphore_Simple::tryacquire (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire"); + return this->op (-1, n, flags | IPC_NOWAIT); +} + +// Non-blocking version of acquire(). + +inline int +ACE_SV_Semaphore_Simple::tryacquire_read (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire_read"); + return this->tryacquire (n, flags); +} + +// Non-blocking version of acquire(). + +inline int +ACE_SV_Semaphore_Simple::tryacquire_write (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::tryacquire_write"); + return this->tryacquire (n, flags); +} + +// Increment ACE_SV_Semaphore by one. Dijkstra's V operation, +// Tannenbaums UP operation. + +inline int +ACE_SV_Semaphore_Simple::release (int n, int flags) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::release"); + return this->op (1, n, flags); +} + +inline int +ACE_SV_Semaphore_Simple::get_id (void) const +{ + ACE_TRACE ("ACE_SV_Semaphore_Simple::get_id"); + return this->internal_id_; +} + diff --git a/ace/SV_Shared_Memory.cpp b/ace/SV_Shared_Memory.cpp new file mode 100644 index 00000000000..8cfc1adc2c8 --- /dev/null +++ b/ace/SV_Shared_Memory.cpp @@ -0,0 +1,82 @@ +// SV_Shared_Memory.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/SV_Shared_Memory.h" +#include "ace/Log_Msg.h" + +#if !defined (__ACE_INLINE__) +#include "ace/SV_Shared_Memory.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_SV_Shared_Memory) + +void +ACE_SV_Shared_Memory::dump (void) const +{ + ACE_TRACE ("ACE_SV_Shared_Memory::dump"); +} + +// Creates a shared memory segment of SIZE bytes and *does* attach to +// this segment. + +int +ACE_SV_Shared_Memory::open_and_attach (key_t external_id, + size_t sz, + int create, + int perms, + void *virtual_addr, + int flags) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::open_and_attach"); + if (this->open (external_id, sz, create, perms) == -1) + return -1; + else if (this->attach (virtual_addr, flags) == -1) + return -1; + else + return 0; +} + +// Constructor interface to this->open_and_attach () member function. + +ACE_SV_Shared_Memory::ACE_SV_Shared_Memory (key_t external_id, + size_t sz, + int create, + int perms, + void *virtual_addr, + int flags) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory"); + if (this->open_and_attach (external_id, sz, create, + perms, virtual_addr, flags) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SV_Shared_Memory::ACE_SV_Shared_Memory")); +} + +// The "do nothing" constructor. + +ACE_SV_Shared_Memory::ACE_SV_Shared_Memory (void) + : segment_ptr_ (0), + internal_id_ (0), + size_ (0) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory"); +} + +// Added this constructor to accept an internal id, the one generated +// when a server constructs with the key IPC_PRIVATE. The client can +// be passed ACE_SV_Shared_Memory::internal_id via a socket and call +// this construtor to attach the existing segment. This prevents +// having to hard-code a key in advance. Courtesy of Marvin Wolfthal +// (maw@fsg.com). + +ACE_SV_Shared_Memory::ACE_SV_Shared_Memory (ACE_HANDLE int_id, + int flags) + : internal_id_ (int_id), + size_ (0) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::ACE_SV_Shared_Memory"); + if (this->attach (0, flags) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_SV_Shared_Memory::ACE_SV_Shared_Memory")); +} diff --git a/ace/SV_Shared_Memory.h b/ace/SV_Shared_Memory.h new file mode 100644 index 00000000000..b7de7c8febb --- /dev/null +++ b/ace/SV_Shared_Memory.h @@ -0,0 +1,107 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// SV_Shared_Memory.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SV_SHARED_MEMORY_H) +#define ACE_SV_SHARED_MEMORY_H + +#include "ace/ACE.h" + +class ACE_Export ACE_SV_Shared_Memory + // = TITLE + // This is a wrapper for System V shared memory. +{ +public: + enum + { + ACE_CREATE = IPC_CREAT, + ACE_OPEN = 0 + }; + + // = Initialization and termination methods. + ACE_SV_Shared_Memory (void); + ACE_SV_Shared_Memory (key_t external_id, + size_t size, + int create, + int perms = ACE_DEFAULT_PERMS, + void *virtual_addr = 0, + int flags = 0); + + ACE_SV_Shared_Memory (ACE_HANDLE internal_id, + int flags = 0); + + int open (key_t external_id, + size_t size, + int create = ACE_SV_Shared_Memory::ACE_OPEN, + int perms = ACE_DEFAULT_PERMS); + + int open_and_attach (key_t external_id, + size_t size, + int create = ACE_SV_Shared_Memory::ACE_OPEN, + int perms = ACE_DEFAULT_PERMS, + void *virtual_addr = 0, + int flags = 0); + + int attach (void *virtual_addr = 0, + int flags =0); + // Attach this shared memory segment. + + int detach (void); + // Detach this shared memory segment. + + int remove (void); + // Remove this shared memory segment. + + int control (int cmd, void *buf); + // Forward to underlying System V <shmctl>. + + // = Segment-related info. + void *get_segment_ptr (void) const; + int get_segment_size (void) const; + + ACE_HANDLE get_id (void) const; + // Return the ID of the shared memory segment (i.e., an ACE_HANDLE). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + enum + { + ALIGN_WORDB = 8 // Most restrictive alignment. + }; + + ACE_HANDLE internal_id_; + // Internal identifier. + + int size_; + // Size of the mapped segment. + + void *segment_ptr_; + // Pointer to the beginning of the segment. + + int round_up (size_t len); + // Round up to an appropriate page size. +}; + +#if defined (__ACE_INLINE__) +#include "ace/SV_Shared_Memory.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SV_SHARED_MEMORY_H */ diff --git a/ace/SV_Shared_Memory.i b/ace/SV_Shared_Memory.i new file mode 100644 index 00000000000..5ac4df7c133 --- /dev/null +++ b/ace/SV_Shared_Memory.i @@ -0,0 +1,105 @@ +/* -*- C++ -*- */ +// $Id$ + +// SV_Shared_Memory.i + +#include "ace/SV_Shared_Memory.h" + +ACE_INLINE int +ACE_SV_Shared_Memory::round_up (size_t len) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::round_up"); + return (len + ACE_SV_Shared_Memory::ALIGN_WORDB - 1) & ~(ACE_SV_Shared_Memory::ALIGN_WORDB - 1); +} + +// Creates a shared memory segment of SIZE bytes. Does *not* attach +// this memory segment... + +ACE_INLINE int +ACE_SV_Shared_Memory::open (key_t external_id, size_t sz, int create, int perms) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::open"); +#if defined (ACE_WIN32) + ACE_NOTSUP_RETURN (-1); +#else + this->segment_ptr_ = 0; + this->size_ = sz; + + this->internal_id_ = ACE_OS::shmget (external_id, sz, create | perms); + + return this->internal_id_ == -1 ? -1 : 0; +#endif /* ACE_WIN32 */ +} + +// Attachs to the shared memory segment. + +ACE_INLINE int +ACE_SV_Shared_Memory::attach (void *virtual_addr, int flags) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::attach"); +#if defined (ACE_WIN32) + ACE_NOTSUP_RETURN (-1); +#else + this->segment_ptr_ = ACE_OS::shmat (this->internal_id_, virtual_addr, flags); + return this->segment_ptr_ == (void *) -1 ? -1 : 0; +#endif /* ACE_WIN32 */ +} + +// Interface to the underlying shared memory control function. + +ACE_INLINE int +ACE_SV_Shared_Memory::control (int cmd, void *buf) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::control"); +#if defined (ACE_WIN32) + ACE_NOTSUP_RETURN (-1); +#else + return ACE_OS::shmctl (this->internal_id_, cmd, (struct shmid_ds *) buf); +#endif /* ACE_WIN32 */ +} + +// The overall size of the segment. + +ACE_INLINE int +ACE_SV_Shared_Memory::get_segment_size (void) const +{ + ACE_TRACE ("ACE_SV_Shared_Memory::get_segment_size"); + return this->size_; +} + +// Removes the shared memory segment. + +ACE_INLINE int +ACE_SV_Shared_Memory::remove (void) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::remove"); +#if defined (ACE_WIN32) + ACE_NOTSUP_RETURN (-1); +#else + return ACE_OS::shmctl (this->internal_id_, IPC_RMID, 0); +#endif /* ACE_WIN32 */ +} + +// Detach the current binding between this->segment_ptr and the shared +// memory segment. + +ACE_INLINE int +ACE_SV_Shared_Memory::detach (void) +{ + ACE_TRACE ("ACE_SV_Shared_Memory::detach"); + return ACE_OS::shmdt (this->segment_ptr_); +} + +ACE_INLINE void * +ACE_SV_Shared_Memory::get_segment_ptr (void) const +{ + ACE_TRACE ("ACE_SV_Shared_Memory::get_segment_ptr"); + return this->segment_ptr_; +} + +ACE_INLINE ACE_HANDLE +ACE_SV_Shared_Memory::get_id (void) const +{ + ACE_TRACE ("ACE_SV_Shared_Memory::get_id"); + return this->internal_id_; +} diff --git a/ace/Service_Config.cpp b/ace/Service_Config.cpp new file mode 100644 index 00000000000..991ea1f9d76 --- /dev/null +++ b/ace/Service_Config.cpp @@ -0,0 +1,928 @@ +// Service_Config.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Svc_Conf.h" +#include "ace/Get_Opt.h" +#include "ace/ARGV.h" +#include "ace/Malloc.h" +#include "ace/Service_Manager.h" +#include "ace/Service_Repository.h" +#include "ace/Service_Record.h" +#include "ace/Set.h" +#include "ace/Auto_Ptr.h" +#include "ace/Service_Config.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Service_Config.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Config) + +void +ACE_Service_Config::dump (void) const +{ + ACE_TRACE ("ACE_Service_Config::dump"); +} + +// All the factory functions that allocate default statically linked +// services should be placed below. + +// Allocate a Service Manager. + +ACE_SVC_FACTORY_DEFINE (ACE_Service_Manager) + +// ---------------------------------------- +// Process-wide Service Repository. +/* static */ +ACE_Service_Repository *ACE_Service_Config::svc_rep_ = 0; + +// Controls whether the Service_Repository is deleted when we shut +// down (we can only delete it safely if we created it!) +/* static */ +int ACE_Service_Config::delete_svc_rep_ = 0; + +// Process-wide Thread Manager. +/* static */ +ACE_Thread_Manager *ACE_Service_Config::thr_mgr_ = 0; + +// Controls whether the Thread_Manager is deleted when we shut down +// (we can only delete it safely if we created it!) +/* static */ +int ACE_Service_Config::delete_thr_mgr_ = 0; + +// Process-wide ACE_Allocator. +/* static */ +ACE_Allocator *ACE_Service_Config::allocator_ = 0; + +// Controls whether the Allocator is deleted when we shut down (we can +// only delete it safely if we created it!) +/* static */ +int ACE_Service_Config::delete_allocator_ = 0; + +// Process-wide ACE_Proactor. +/* static */ +ACE_Proactor *ACE_Service_Config::proactor_ = 0; + +// Controls whether the Proactor is deleted when we shut down (we can +// only delete it safely if we created it!) +/* static */ +int ACE_Service_Config::delete_proactor_ = 0; + +// Process-wide ACE_Reactor. +/* static */ +ACE_Reactor *ACE_Service_Config::reactor_ = 0; + +// Controls whether the Reactor is deleted when we shut down (we can +// only delete it safely if we created it!) +/* static */ +int ACE_Service_Config::delete_reactor_ = 0; + +// Process-wide ACE_ReactorEx. +/* static */ +ACE_ReactorEx *ACE_Service_Config::reactorEx_ = 0; + +// Controls whether the ReactorEx is deleted when we shut down (we can +// only delete it safely if we created it!) +/* static */ +int ACE_Service_Config::delete_reactorEx_ = 0; + +// Make this the default. +typedef ACE_Malloc <ACE_Local_Memory_Pool, ACE_Null_Mutex> + ACE_DEFAULT_MALLOC; + +// Terminate the eventloop. +/* static */ +sig_atomic_t ACE_Service_Config::end_reactor_event_loop_ = 0; +sig_atomic_t ACE_Service_Config::end_proactor_event_loop_ = 0; +sig_atomic_t ACE_Service_Config::end_reactorEx_event_loop_ = 0; + +// Trigger a reconfiguration. +/* static */ +sig_atomic_t ACE_Service_Config::reconfig_occurred_ = 0; + + // = Set by command-line options. +/* static */ +char ACE_Service_Config::debug_ = 0; +char ACE_Service_Config::be_a_daemon_ = 0; +char ACE_Service_Config::no_defaults_ = 0; + +// Number of the signal used to trigger reconfiguration. +/* static */ +int ACE_Service_Config::signum_ = SIGHUP; + +// Name of the service configuration file. +const char *ACE_Service_Config::service_config_file_ = ACE_DEFAULT_SVC_CONF; + +// Name of file used to store messages. +const char *ACE_Service_Config::logger_key_ = "/tmp/server_daemon"; + +// Define the object that describes the service statically. +ACE_STATIC_SVC_DEFINE (ACE_Service_Manager, + "ACE_Service_Manager", ACE_SVC_OBJ_T, &ACE_SVC_NAME (ACE_Service_Manager), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, 0) + +ACE_STATIC_SVC_REQUIRE (ACE_Service_Manager) + +// List of statically configured services. + +ACE_STATIC_SVCS * +ACE_Service_Config::static_svcs (void) +{ + static ACE_STATIC_SVCS *instance_ = 0; + + // Add other default services here if you'd like. + + if (instance_ == 0) + ACE_NEW_RETURN (instance_, ACE_STATIC_SVCS, 0); + + return instance_; +} + +ACE_Allocator * +ACE_Service_Config::allocator (void) +{ + ACE_TRACE ("ACE_Service_Config::allocator"); + if (ACE_Service_Config::allocator_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::allocator_, + ACE_Allocator_Adapter <ACE_DEFAULT_MALLOC>, + 0); + ACE_Service_Config::delete_allocator_ = 1; + } + return ACE_Service_Config::allocator_; +} + +ACE_Allocator * +ACE_Service_Config::allocator (ACE_Allocator *r) +{ + ACE_TRACE ("ACE_Service_Config::allocator"); + + ACE_Allocator *t = ACE_Service_Config::allocator_; + + // We can't safely delete it since we don't know who created it! + ACE_Service_Config::delete_allocator_ = 0; + + ACE_Service_Config::allocator_ = r; + return t; +} + +ACE_Reactor * +ACE_Service_Config::reactor (void) +{ + ACE_TRACE ("ACE_Service_Config::reactor"); + if (ACE_Service_Config::reactor_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::reactor_, ACE_Reactor, 0); + ACE_Service_Config::delete_reactor_ = 1; + } + return ACE_Service_Config::reactor_; +} + +ACE_Reactor * +ACE_Service_Config::reactor (ACE_Reactor *r) +{ + ACE_TRACE ("ACE_Service_Config::reactor"); + + ACE_Reactor *t = ACE_Service_Config::reactor_; + // We can't safely delete it since we don't know who created it! + ACE_Service_Config::delete_reactor_ = 0; + + ACE_Service_Config::reactor_ = r; + return t; +} + +ACE_Proactor * +ACE_Service_Config::proactor (size_t threads) +{ + ACE_TRACE ("ACE_Service_Config::proactor"); + if (ACE_Service_Config::proactor_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::proactor_, ACE_Proactor (threads), 0); + ACE_Service_Config::delete_proactor_ = 1; + } + return ACE_Service_Config::proactor_; +} + +ACE_Proactor * +ACE_Service_Config::proactor (ACE_Proactor *r) +{ + ACE_TRACE ("ACE_Service_Config::proactor"); + + ACE_Proactor *t = ACE_Service_Config::proactor_; + // We can't safely delete it since we don't know who created it! + ACE_Service_Config::delete_proactor_ = 0; + + ACE_Service_Config::proactor_ = r; + return t; +} + +ACE_ReactorEx * +ACE_Service_Config::reactorEx (void) +{ + ACE_TRACE ("ACE_Service_Config::reactorEx"); + if (ACE_Service_Config::reactorEx_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::reactorEx_, ACE_ReactorEx, 0); + ACE_Service_Config::delete_reactorEx_ = 1; + } + + return ACE_Service_Config::reactorEx_; +} + +ACE_ReactorEx * +ACE_Service_Config::reactorEx (ACE_ReactorEx *r) +{ + ACE_TRACE ("ACE_Service_Config::reactorEx"); + + ACE_ReactorEx *t = ACE_Service_Config::reactorEx_; + // We can't safely delete it since we don't know who created it! + ACE_Service_Config::delete_reactorEx_ = 0; + + ACE_Service_Config::reactorEx_ = r; + return t; +} + +ACE_Service_Repository * +ACE_Service_Config::svc_rep (void) +{ + ACE_TRACE ("ACE_Service_Config::svc_rep"); + + if (ACE_Service_Config::svc_rep_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::svc_rep_, ACE_Service_Repository, 0); + ACE_Service_Config::delete_svc_rep_ = 1; + } + + return ACE_Service_Config::svc_rep_; +} + +ACE_Service_Repository * +ACE_Service_Config::svc_rep (ACE_Service_Repository *s) +{ + ACE_TRACE ("ACE_Service_Config::svc_rep"); + + ACE_Service_Repository *t = ACE_Service_Config::svc_rep_; + // We can't safely delete it since we don't know who created it! + ACE_Service_Config::delete_svc_rep_ = 0; + + ACE_Service_Config::svc_rep_ = s; + return t; +} + +ACE_Thread_Manager * +ACE_Service_Config::thr_mgr (void) +{ + ACE_TRACE ("ACE_Service_Config::thr_mgr"); + + if (ACE_Service_Config::thr_mgr_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::thr_mgr_, ACE_Thread_Manager, 0); + ACE_Service_Config::delete_thr_mgr_ = 1; + } + + return ACE_Service_Config::thr_mgr_; +} + +ACE_Thread_Manager * +ACE_Service_Config::thr_mgr (ACE_Thread_Manager *tm) +{ + ACE_TRACE ("ACE_Service_Config::thr_mgr"); + + ACE_Thread_Manager *t = ACE_Service_Config::thr_mgr_; + // We can't safely delete it since we don't know who created it! + ACE_Service_Config::delete_thr_mgr_ = 0; + + ACE_Service_Config::thr_mgr_ = tm; + return t; +} + +// Totally remove <svc_name> from the daemon by removing it from the +// ACE_Reactor, and unlinking it if necessary. + +int +ACE_Service_Config::remove (const char svc_name[]) +{ + ACE_TRACE ("ACE_Service_Config::remove"); + return ACE_Service_Config::svc_rep ()->remove (svc_name); +} + +// Suspend SVC_NAME. Note that this will not unlink the service from +// the daemon if it was dynamically linked, it will mark it as being +// suspended in the Service Repository and call the suspend() member +// function on the appropriate ACE_Service_Object. A service can be +// resumed later on by calling the RESUME() member function... + +int +ACE_Service_Config::suspend (const char svc_name[]) +{ + ACE_TRACE ("ACE_Service_Config::suspend"); + return ACE_Service_Config::svc_rep ()->suspend (svc_name); +} + +// Resume a SVC_NAME that was previously suspended or has not yet +// been resumed (e.g., a static service). + +int +ACE_Service_Config::resume (const char svc_name[]) +{ + ACE_TRACE ("ACE_Service_Config::resume"); + return ACE_Service_Config::svc_rep ()->resume (svc_name); +} + +// Initialize the Service Repository. Note that this *must* +// be performed in the constructor (rather than open()) since +// otherwise the repository will not be properly initialized +// to allow static configuration of services... + +ACE_Service_Config::ACE_Service_Config (int ignore_defaults, + size_t size, + int signum) +{ + ACE_TRACE ("ACE_Service_Config::ACE_Service_Config"); + ACE_Service_Config::no_defaults_ = ignore_defaults; + ACE_Service_Config::signum_ = signum; + + // Initialize the Service Repository. + + if (ACE_Service_Config::svc_rep_ == 0) + { + ACE_NEW (ACE_Service_Config::svc_rep_, + ACE_Service_Repository (size)); + + // We created it, so we own it! + ACE_Service_Config::delete_svc_rep_ = 1; + } + + // Initialize the ACE_Reactor (the ACE_Reactor should be the same + // size as the ACE_Service_Repository). + + if (ACE_Service_Config::reactor_ == 0) + { + ACE_NEW (ACE_Service_Config::reactor_, + ACE_Reactor (size)); + + // We created it, so we own it! + ACE_Service_Config::delete_reactor_ = 1; + } + +// There's no point in dealing with this on NT since it doesn't really +// support signals very well... +#if !defined (ACE_WIN32) + // This really ought to be a Singleton I suspect... + + if (ACE_Service_Config::reactor_->register_handler + (ACE_Service_Config::signum_, this) == -1) + ACE_ERROR ((LM_ERROR, "can't register signal handler\n")); +#endif /* !ACE_WIN32 */ +} + +// Handle the command-line options intended for the +// ACE_Service_Config. + +void +ACE_Service_Config::parse_args (int argc, char *argv[]) +{ + ACE_TRACE ("ACE_Service_Config::parse_args"); + ACE_Get_Opt getopt (argc, argv, "bdf:ns:", 1); // Start at argv[1] + + for (int c; (c = getopt ()) != -1; ) + switch (c) + { + case 'b': + ACE_Service_Config::be_a_daemon_ = 1; + break; + case 'd': + ACE_Service_Config::debug_ = 1; + break; + case 'f': + ACE_Service_Config::service_config_file_ = getopt.optarg; + break; + case 'n': + ACE_Service_Config::no_defaults_ = 1; + break; + case 's': + { +// There's no point in dealing with this on NT since it doesn't really +// support signals very well... +#if !defined (ACE_WIN32) + ACE_Event_Handler *eh = 0; + + if (ACE_Service_Config::reactor ()->handler + (ACE_Service_Config::signum_, &eh) == -1) + ACE_ERROR ((LM_ERROR, "cannot obtain signal handler\n")); + + ACE_Service_Config::signum_ = ACE_OS::atoi (getopt.optarg); + + if (ACE_Service_Config::reactor ()->register_handler + (ACE_Service_Config::signum_, eh) == -1) + ACE_ERROR ((LM_ERROR, "cannot obtain signal handler\n")); +#endif /* !ACE_WIN32 */ + break; + } + default: + ACE_ERROR ((LM_ERROR, "%c is not a ACE_Service_Config option\n", c)); + break; + } +} + +// Initialize and activate a statically linked service. + +int +ACE_Service_Config::initialize (const char svc_name[], + char *parameters) +{ + ACE_TRACE ("ACE_Service_Config::initialize"); + ACE_ARGV args (parameters); + ACE_Service_Record *srp = 0; + + ACE_DEBUG ((LM_DEBUG, "opening static service %s\n", svc_name)); + + if (ACE_Service_Config::svc_rep ()->find + (svc_name, (const ACE_Service_Record **) &srp) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%s not found\n", svc_name), -1); + + else if (srp->type ()->init (args.argc (), args.argv ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "static initialization failed, %p\n", + svc_name), -1); + else + { + srp->active (1); + return 0; + } +} + +// Dynamically link the shared object file and retrieve a pointer to +// the designated shared object in this file. + +int +ACE_Service_Config::initialize (const ACE_Service_Record *sr, + char parameters[]) +{ + ACE_TRACE ("ACE_Service_Config::initialize"); + ACE_ARGV args (parameters); + + ACE_DEBUG ((LM_DEBUG, "opening dynamic service %s\n", sr->name ())); + + if (ACE_Service_Config::svc_rep ()->insert (sr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "insertion failed, %p\n", sr->name ()), -1); + + else if (sr->type ()->init (args.argc (), args.argv ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "dynamic initialization failed for %s\n", + sr->name ()), -1); + else + return 0; +} + +// Process service configuration requests as indicated in the +// <service_config_file>. + +int +ACE_Service_Config::process_directives (void) +{ + ACE_TRACE ("ACE_Service_Config::process_directives"); + + FILE *fp = ACE_OS::fopen (ACE_Service_Config::service_config_file_, "r"); + + if (fp == 0) + { + errno = ENOENT; + return -1; // No service configuration file + } + else + { + ace_yyrestart (fp); + + ace_yyerrno = 0; + ace_yylineno = 1; + + // Use an auto_ptr to make sure that we release this memory + // regardless of how we exit... + ACE_NEW_RETURN (ace_obstack, ACE_Obstack, -1); + + auto_ptr<ACE_Obstack> holder (ace_obstack); + + ace_yyparse (); + + if (ace_yyerrno > 0) + errno = EINVAL; // This is a hack, better errors should be provided... + + return ace_yyerrno; + } +} + +// Add the default statically-linked services to the Service +// Repository. + +int +ACE_Service_Config::load_defaults (void) +{ + ACE_TRACE ("ACE_Service_Config::load_defaults"); + + ACE_Static_Svc_Descriptor **ssdp = 0; + ACE_STATIC_SVCS &svcs = *ACE_Service_Config::static_svcs (); + + for (ACE_STATIC_SVCS_ITERATOR iter (svcs); + iter.next (ssdp) != 0; + iter.advance ()) + { + ACE_Static_Svc_Descriptor *ssd = *ssdp; + + ACE_Service_Type *stp = + ace_create_service_type (ssd->name_, + ssd->type_, + (const void *) (*ssd->alloc_)(), + ssd->flags_); + if (stp == 0) + continue; + + const ACE_Service_Record *sr; + + ACE_NEW_RETURN (sr, ACE_Service_Record (ssd->name_, stp, + 0, ssd->active_), -1); + + if (ACE_Service_Config::svc_rep ()->insert (sr) == -1) + return -1; + } + return 0; +} + +// Performs an open without parsing command-line arguments. + +int +ACE_Service_Config::open (const char program_name[]) +{ + ACE_TRACE ("ACE_Service_Config::open"); + + // Only use STDERR if the users hasn't yet set the flags. + if (ACE_LOG_MSG->open (program_name, + ACE_LOG_MSG->flags() ? ACE_LOG_MSG->flags() : ACE_Log_Msg::STDERR, + ACE_Service_Config::logger_key_) == -1) + return -1; + ACE_DEBUG ((LM_STARTUP, "starting up daemon %n\n")); + + // Initialize the Service Repository (this will still work if user + // forgets to define an object of type ACE_Service_Config). + + if (ACE_Service_Config::svc_rep_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::svc_rep_, + ACE_Service_Repository (ACE_Service_Config::MAX_SERVICES), -1); + + // We created it, so we own it! + ACE_Service_Config::delete_svc_rep_ = 1; + } + + // Initialize the ACE_Reactor (the ACE_Reactor should be the same + // size as the ACE_Service_Repository). + + if (ACE_Service_Config::reactor_ == 0) + { + ACE_NEW_RETURN (ACE_Service_Config::reactor_, + ACE_Reactor (ACE_Service_Config::MAX_SERVICES), -1); + // We created it, so we own it! + ACE_Service_Config::delete_reactor_ = 1; + } + + if (ACE_Service_Config::be_a_daemon_) + ACE_Service_Config::start_daemon (); + + // Register ourselves to receive reconfiguration requests via + // signals! + + if (ACE_Service_Config::no_defaults_ == 0 + && ACE_Service_Config::load_defaults () == -1) + return -1; + else + return ACE_Service_Config::process_directives (); +} + +ACE_Service_Config::ACE_Service_Config (const char program_name[]) +{ + ACE_TRACE ("ACE_Service_Config::ACE_Service_Config"); + + if (this->open (program_name) == -1 + && errno != ENOENT) + // Only print out an error if it wasn't the svc.conf file that was + // missing. + ACE_ERROR ((LM_ERROR, "%p\n", program_name)); +} + +// Signal handling API to trigger dynamic reconfiguration. + +int +ACE_Service_Config::handle_signal (int sig, siginfo_t *, ucontext_t *) +{ + ACE_TRACE ("ACE_Service_Config::handle_signal"); + + if (ACE_Service_Config::signum_ != sig) + ACE_ERROR ((LM_ERROR, + "error, signal %S does match %S\n", + sig, ACE_Service_Config::signum_)); + + if (ACE_Service_Config::debug_) + ACE_DEBUG ((LM_DEBUG, "signal %S occurred\n", sig)); + + ACE_Service_Config::reconfig_occurred_ = 1; + return 0; +} + +// Trigger the reconfiguration process. + +void +ACE_Service_Config::reconfigure (void) +{ + ACE_TRACE ("ACE_Service_Config::reconfigure"); + + ACE_Service_Config::reconfig_occurred_ = 0; + + if (ACE_Service_Config::debug_) + { + time_t t = ACE_OS::time (0); + ACE_DEBUG ((LM_DEBUG, "beginning reconfiguration at %s", ACE_OS::ctime (&t))); + } + + if (ACE_Service_Config::process_directives () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "process_directives")); +} + +// Run the event loop until the <ACE_Reactor::handle_events> +// method returns -1 or the <end_reactor_event_loop> method +// is invoked. + +int +ACE_Service_Config::run_reactor_event_loop (void) +{ + ACE_TRACE ("ACE_Service_Config::run_reactor_event_loop"); + + while (ACE_Service_Config::end_reactor_event_loop_ == 0) + { + int result = ACE_Service_Config::reactor ()->handle_events (); + + if (ACE_Service_Config::reconfig_occurred_) + ACE_Service_Config::reconfigure (); + + else if (result == -1) + return -1; + } + /* NOTREACHED */ + return 0; +} + +// Run the event loop until the <ACE_Reactor::handle_events> +// method returns -1, the <end_reactor_event_loop> method +// is invoked, or the <ACE_Time_Value> expires. + +int +ACE_Service_Config::run_reactor_event_loop (ACE_Time_Value &tv) +{ + ACE_TRACE ("ACE_Service_Config::run_reactor_event_loop"); + + while (ACE_Service_Config::end_reactor_event_loop_ == 0) + { + int result = ACE_Service_Config::reactor ()->handle_events (tv); + if (ACE_Service_Config::reconfig_occurred_) + ACE_Service_Config::reconfigure (); + else if (result == -1) + return -1; + } + + /* NOTREACHED */ + return 0; +} + +// Tidy up and perform last rites on a terminating ACE_Service_Config. +int +ACE_Service_Config::close (void) +{ + ACE_TRACE ("ACE_Service_Config::close"); + + if (ACE_Service_Config::svc_rep_ != 0) + { + ACE_DEBUG ((LM_SHUTDOWN, "shutting down daemon %n\n")); + + // ACE_Service_Config must be deleted first so that an object's + // fini() method may reference a valid ACE_Reactor. + ACE_Service_Config::close_svcs (); + ACE_Service_Config::close_singletons (); + } + return 0; +} + +int +ACE_Service_Config::close_svcs (void) +{ + ACE_TRACE ("ACE_Service_Config::close_svcs"); + + if (ACE_Service_Config::delete_svc_rep_) + { + delete ACE_Service_Config::svc_rep_; + ACE_Service_Config::svc_rep_ = 0; + } + + return 0; +} + +int +ACE_Service_Config::close_singletons (void) +{ + ACE_TRACE ("ACE_Service_Config::close_singletons"); + + if (ACE_Service_Config::delete_reactor_) + { + delete ACE_Service_Config::reactor_; + ACE_Service_Config::reactor_ = 0; + } + + if (ACE_Service_Config::delete_proactor_) + { + delete ACE_Service_Config::proactor_; + ACE_Service_Config::proactor_ = 0; + } + + if (ACE_Service_Config::delete_reactorEx_) + { + delete ACE_Service_Config::reactorEx_; + ACE_Service_Config::reactorEx_ = 0; + } + + if (ACE_Service_Config::delete_thr_mgr_) + { + delete ACE_Service_Config::thr_mgr_; + ACE_Service_Config::thr_mgr_ = 0; + } + + if (ACE_Service_Config::delete_allocator_) + { + delete ACE_Service_Config::allocator_; + ACE_Service_Config::allocator_ = 0; + } + return 0; +} + +// Perform user-specified close activities and remove dynamic memory. + + +ACE_Service_Config::~ACE_Service_Config (void) +{ + ACE_TRACE ("ACE_Service_Config::~ACE_Service_Config"); + ACE_Service_Config::close (); +} + +/* static */ +int +ACE_Service_Config::end_reactor_event_loop (void) +{ + ACE_TRACE ("ACE_Service_Config::end_reactor_event_loop"); + ACE_Service_Config::end_reactor_event_loop_ = 1; + + return ACE_Service_Config::reactor ()->notify (); +} + +/* static */ +sig_atomic_t +ACE_Service_Config::reactor_event_loop_done (void) +{ + ACE_TRACE ("ACE_Service_Config::end_proactor_event_loop"); + return ACE_Service_Config::end_reactor_event_loop_; +} + +int +ACE_Service_Config::run_proactor_event_loop (void) +{ + ACE_TRACE ("ACE_Service_Config::run_proactor_event_loop"); + + while (ACE_Service_Config::end_proactor_event_loop_ == 0) + { + int result = ACE_Service_Config::proactor ()->handle_events (); + + if (ACE_Service_Config::reconfig_occurred_) + ACE_Service_Config::reconfigure (); + + else if (result == -1) + return -1; + } + /* NOTREACHED */ + return 0; +} + +int +ACE_Service_Config::run_proactor_event_loop (ACE_Time_Value &tv) +{ + ACE_TRACE ("ACE_Service_Config::run_proactor_event_loop"); + + while (ACE_Service_Config::end_proactor_event_loop_ == 0) + { + int result = ACE_Service_Config::proactor ()->handle_events (tv); + if (ACE_Service_Config::reconfig_occurred_) + ACE_Service_Config::reconfigure (); + else if (result == -1) + return -1; + } + + /* NOTREACHED */ + return 0; +} + +int +ACE_Service_Config::end_proactor_event_loop (void) +{ + ACE_TRACE ("ACE_Service_Config::end_proactor_event_loop"); + ACE_Service_Config::end_proactor_event_loop_ = 1; + // ACE_Service_Config::proactor ()->notify (); + return 0; +} + +/* static */ +sig_atomic_t +ACE_Service_Config::proactor_event_loop_done (void) +{ + ACE_TRACE ("ACE_Service_Config::end_proactor_event_loop"); + return ACE_Service_Config::end_proactor_event_loop_; +} + +// ************************************************************ + +int +ACE_Service_Config::run_reactorEx_event_loop (void) +{ + ACE_TRACE ("ACE_Service_Config::run_reactorEx_event_loop"); + + while (ACE_Service_Config::end_reactorEx_event_loop_ == 0) + { + int result = ACE_Service_Config::reactorEx ()->handle_events (); + + if (ACE_Service_Config::reconfig_occurred_) + ACE_Service_Config::reconfigure (); + + else if (result == -1) + return -1; + } + /* NOTREACHED */ + return 0; +} + +int +ACE_Service_Config::run_reactorEx_event_loop (ACE_Time_Value &tv) +{ + ACE_TRACE ("ACE_Service_Config::run_reactorEx_event_loop"); + + while (ACE_Service_Config::end_reactorEx_event_loop_ == 0) + { + int result = ACE_Service_Config::reactorEx ()->handle_events (tv); + if (ACE_Service_Config::reconfig_occurred_) + ACE_Service_Config::reconfigure (); + else if (result == -1) + return -1; + } + + /* NOTREACHED */ + return 0; +} + +int +ACE_Service_Config::end_reactorEx_event_loop (void) +{ + ACE_TRACE ("ACE_Service_Config::end_reactorEx_event_loop"); + ACE_Service_Config::end_reactorEx_event_loop_ = 1; + return ACE_Service_Config::reactorEx ()->notify (); +} + +/* static */ +sig_atomic_t +ACE_Service_Config::reactorEx_event_loop_done (void) +{ + ACE_TRACE ("ACE_Service_Config::end_reactorEx_event_loop"); + return ACE_Service_Config::end_reactorEx_event_loop_; +} + +// ************************************************************ + +/* static */ +sig_atomic_t +ACE_Service_Config::reconfig_occurred (void) +{ + ACE_TRACE ("ACE_Service_Config::reconfig_occurred"); + return ACE_Service_Config::reconfig_occurred_; +} + +void +ACE_Service_Config::reconfig_occurred (sig_atomic_t config_occurred) +{ + ACE_TRACE ("ACE_Service_Config::reconfig_occurred"); + ACE_Service_Config::reconfig_occurred_ = config_occurred; +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Set_Node<ACE_Static_Svc_Descriptor *>; +template class ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *>; +template class ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *>; +template class ACE_Malloc<ACE_Local_Memory_Pool, ACE_Null_Mutex>; +template class ACE_Allocator_Adapter<ACE_Malloc<ACE_Local_Memory_Pool, ACE_Null_Mutex> >; +template class auto_ptr<ACE_Obstack>; +#if !defined (ACE_HAS_THREADS) +template class ACE_Guard<ACE_Null_Mutex>; +template class ACE_Read_Guard<ACE_Null_Mutex>; +template class ACE_Write_Guard<ACE_Null_Mutex>; +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Service_Config.h b/ace/Service_Config.h new file mode 100644 index 00000000000..52fbdb86090 --- /dev/null +++ b/ace/Service_Config.h @@ -0,0 +1,353 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Service_Config.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SERVICE_CONFIG_H) +#define ACE_SERVICE_CONFIG_H + +#include "ace/Service_Object.h" +#include "ace/Thread_Manager.h" +#include "ace/Set.h" +#include "ace/Proactor.h" +#include "ace/ReactorEx.h" + +// Forward decl. +class ACE_Service_Repository; +class ACE_Service_Record; +class ACE_Allocator; +class ACE_Reactor; +//class ACE_Proactor; + +struct ACE_Static_Svc_Descriptor +{ + char *name_; + // Name of the service. + + int type_; + // Type of service. + + ACE_Service_Object *(*alloc_)(void); + // Factory function that allocates the service. + + u_int flags_; + // Bitmask flags indicating how the framework should delete memory. + + int active_; + // Flag indicating whether the service starts out active. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +public: + int operator== (ACE_Static_Svc_Descriptor &) const; + // Compare two service descriptors for equality. +}; + +// = Maintain a set of the statically linked service descriptor. + +typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *> ACE_STATIC_SVCS; +typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *> ACE_STATIC_SVCS_ITERATOR; + +class ACE_Export ACE_Service_Config : public ACE_Event_Handler + // = TITLE + // Provide the base class that supplies common server daemon + // operations. + // + // = DESCRIPTION + // This class inherits from <ACE_Event_Handler> so that it can + // be used as a signal handler. +{ +public: + enum {MAX_SERVICES = ACE_DEFAULT_REACTOR_SIZE}; + + // = Initialization and termination methods. + + ACE_Service_Config (int ignore_defaults = 0, + size_t size = ACE_Service_Config::MAX_SERVICES, + int signum = SIGHUP); + // Initialize the Service Repository. + + ACE_Service_Config (const char program_name[]); + // Performs an open without parsing command-line arguments. + + static int open (const char program_name[]); + // Performs an open without parsing command-line arguments. + + static int open (int argc, char *argv[]); + // This is the primary entry point into the ACE_Service_Config (the + // constructor just handles simple initializations). It parses + // arguments passed in from the command-line. + + virtual ~ACE_Service_Config (void); + // Perform user-specified close activities and remove dynamic + // memory. + + static int close (void); + // Tidy up and perform last rites when ACE_Service_Config is shut + // down. This method calls <close_svcs> and <close_singletons>. + + static int close_svcs (void); + // Perform user-specified close hooks on all of the configured + // services in the <Service_Repository>, then delete the + // <Service_Repository> itself. + + static int close_singletons (void); + // Delete the dynamically allocated Singletons (i.e., the <Reactor>, + // <Proactor>, <ReactorEx>, <Thread_Manager>, and <Allocator>). + + // = Reactor event loop management methods. + static int run_reactor_event_loop (void); + // Run the event loop until the <ACE_Reactor::handle_events> method + // returns -1 or the <end_reactor_event_loop> method is invoked. + + static int run_reactor_event_loop (ACE_Time_Value &tv); + // Run the event loop until the <ACE_Reactor::handle_events> method + // returns -1, the <end_reactor_event_loop> method is invoked, or the + // <ACE_Time_Value> expires. + + static int end_reactor_event_loop (void); + // Instruct the <ACE_Service_Config> to terminate its event loop and + // notifies the <ACE_Service_Config::reactor> so that it can wake up + // and close down gracefully. + + static sig_atomic_t reactor_event_loop_done (void); + // Report if the Reactor's event loop is finished. + + // = Proactor event loop management methods. + static int run_proactor_event_loop (void); + // Run the event loop until the <ACE_Proactor::handle_events> + // method returns -1 or the <end_proactor_event_loop> method + // is invoked. + + static int run_proactor_event_loop (ACE_Time_Value &tv); + // Run the event loop until the <ACE_Proactor::handle_events> + // method returns -1, the <end_proactor_event_loop> method + // is invoked, or the <ACE_Time_Value> expires. + + static int end_proactor_event_loop (void); + // Instruct the <ACE_Service_Config> to terminate its event loop. + + static sig_atomic_t proactor_event_loop_done (void); + // Report if the proactor event loop is finished. + + // = ReactorEx event loop management methods. + static int run_reactorEx_event_loop (void); + // Run the event loop until the <ACE_ReactorEx::handle_events> + // method returns -1 or the <end_reactorEx_event_loop> method + // is invoked. + + static int run_reactorEx_event_loop (ACE_Time_Value &tv); + // Run the event loop until the <ACE_ReactorEx::handle_events> + // method returns -1, the <end_reactorEx_event_loop> method + // is invoked, or the <ACE_Time_Value> expires. + + static int end_reactorEx_event_loop (void); + // Instruct the <ACE_Service_Config> to terminate its event loop. + + static sig_atomic_t reactorEx_event_loop_done (void); + // Report if the ReactorEx event loop is finished. + + static sig_atomic_t reconfig_occurred (void); + // True if reconfiguration occurred. + + static void reconfig_occurred (sig_atomic_t); + // Indicate that reconfiguration occurred. + + // = The following methods are static in order to enforce Singleton + // semantics for the Reactor, Service_Repository, Thread_Manager, + // Acceptor/Connector Strategy factory, Proactor, and ReactorEx. + // Other portions of the system may need to access them at some + // point or another... + + // = Accessors and mutators for process-wide Singletons. + + static ACE_STATIC_SVCS *static_svcs (void); + // Returns a pointer to the list of statically linked services. + + static ACE_Reactor *reactor (void); + // Get pointer to a process-wide <ACE_Reactor>. + + static ACE_Reactor *reactor (ACE_Reactor *); + // Set pointer to a process-wide <ACE_Reactor> and return existing + // pointer. + + static ACE_Proactor *proactor (size_t threads = 0); + // Get pointer to a process-wide <ACE_Proactor>. <threads> should + // be part of another method. It's only here because I'm just a + // grad student and not in charge. No, I'm not bitter about this. + + static ACE_Proactor *proactor (ACE_Proactor *); + // Set pointer to a process-wide <ACE_Proactor> and return existing + // pointer. + + static ACE_ReactorEx *reactorEx (void); + // Get pointer to a process-wide <ACE_ReactorEx>. + + static ACE_ReactorEx *reactorEx (ACE_ReactorEx *); + // Set pointer to a process-wide <ACE_ReactorEx> and return existing + // pointer. + + static ACE_Service_Repository *svc_rep (void); + // Get pointer to a process-wide <ACE_Service_Repository>. + + static ACE_Service_Repository *svc_rep (ACE_Service_Repository *); + // Set pointer to a process-wide <ACE_Service_Repository> and return + // existing pointer. + + static ACE_Thread_Manager *thr_mgr (void); + // Get pointer to a process-wide <ACE_Thread_Manager>. + + static ACE_Thread_Manager *thr_mgr (ACE_Thread_Manager *); + // Set pointer to a process-wide <ACE_Thread_Manager> and return + // existing pointer. + + static ACE_Allocator *allocator (void); + // Get pointer to a default <ACE_Allocator>. + + static ACE_Allocator *allocator (ACE_Allocator *); + // Set pointer to a process-wide <ACE_Allocator> and return existing + // pointer. + + // = Member functions used by various other parts + // of the Service Configurator class category. + static int initialize (const ACE_Service_Record *, char parameters[]); + // Dynamically link the shared object file and retrieve + // a pointer to the designated shared object in this file. + + static int initialize (const char svc_name[], char parameters[]); + // Initialize and activate a statically <svc_name> service. + + static int resume (const char svc_name[]); + // Resume a <svc_name> that was previously suspended or has not yet + // been resumed (e.g., a static service). + + static int suspend (const char svc_name[]); + // Suspend <svc_name>. Note that this will not unlink the service + // from the daemon if it was dynamically linked, it will mark it + // as being suspended in the Service Repository and call the + // suspend() member function on the appropriate ACE_Service_Object. + // A service can be resumed later on by calling the RESUME() + // member function... + + static int remove (const char svc_name[]); + // Totally remove <svc_name> from the daemon by removing it + // from the ACE_Reactor, and unlinking it if necessary. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + static int process_directives (void); + // Process service configuration requests as indicated + // in the <service_config_file>. + + static void parse_args (int, char *[]); + // Handle the command-line options intended for the <ACE_Service_Config>. + + static void reconfigure (void); + // Perform the reconfiguration process. + + static int start_daemon (void); + // Become a daemon. + + static int load_defaults (void); + // Add the default statically-linked services to the <ACE_Service_Repository>. + + virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0); + // Signal handling API to trigger dynamic reconfiguration. + +private: + + static ACE_Service_Repository *svc_rep_; + // Pointer to a process-wide <ACE_Service_Repository>. + + static int delete_svc_rep_; + // Must delete the <svc_rep_> if non-0. + + static ACE_Thread_Manager *thr_mgr_; + // Pointer to a process-wide <ACE_Thread_Manager>. + + static int delete_thr_mgr_; + // Must delete the <thr_mgr_> if non-0. + + static ACE_Allocator *allocator_; + // Pointer to a process-wide <ACE_Allocator> instance. + + static int delete_allocator_; + // Must delete the <allocator_> if non-0. + + static ACE_Proactor *proactor_; + // Pointer to a process-wide <ACE_Reactor>. + + static int delete_proactor_; + // Must delete the <proactor_> if non-0. + + static ACE_ReactorEx *reactorEx_; + // Pointer to a process-wide <ACE_Reactor>. + + static int delete_reactorEx_; + // Must delete the <proactor_> if non-0. + + static ACE_Reactor *reactor_; + // Pointer to a process-wide <ACE_Reactor>. + + static int delete_reactor_; + // Must delete the <reactor_> if non-0. + + static const char *service_config_file_; + // Name of service configuration file. + + static const char *logger_key_; + // Where to write the logging output. + + //static ACE_Static_Svc_Descriptor service_list_[]; + // List of statically linked services. + + static sig_atomic_t end_reactor_event_loop_; + // Terminate the event loop. + + static sig_atomic_t end_proactor_event_loop_; + // Terminate the proactor event loop. + + static sig_atomic_t end_reactorEx_event_loop_; + // Terminate the proactor event loop. + + static sig_atomic_t reconfig_occurred_; + // True if reconfiguration occurred. + + // = Set by command-line options. + static char debug_; + static char be_a_daemon_; + static char no_defaults_; + + static int signum_; + // Number of the signal used to trigger reconfiguration. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Service_Config.i" +#endif /* __ACE_INLINE__ */ + +// These must go here to avoid circular includes... +#include "ace/Reactor.h" +#include "ace/Svc_Conf_Tokens.h" +#endif /* ACE_SERVICE_CONFIG_H */ diff --git a/ace/Service_Config.i b/ace/Service_Config.i new file mode 100644 index 00000000000..2940c580a4c --- /dev/null +++ b/ace/Service_Config.i @@ -0,0 +1,32 @@ +/* -*- C++ -*- */ +// $Id$ + +// Service_Config.i + +// Become a daemon (i.e., run as a "background" process). + +ACE_INLINE int +ACE_Service_Config::start_daemon (void) +{ + ACE_TRACE ("ACE_Service_Config::start_daemon"); + return ACE::daemonize (); +} + +// This is the primary entry point into the ACE_Service_Config (the +// constructor just handles simple initializations). + +ACE_INLINE int +ACE_Service_Config::open (int argc, char *argv[]) +{ + ACE_TRACE ("ACE_Service_Config::open"); + ACE_Service_Config::parse_args (argc, argv); + return ACE_Service_Config::open (argv[0]); +} + +// Compare two service descriptors for equality. + +ACE_INLINE int +ACE_Static_Svc_Descriptor::operator== (struct ACE_Static_Svc_Descriptor &d) const +{ + return ACE_OS::strcmp (name_, d.name_) == 0; +} diff --git a/ace/Service_Main.cpp b/ace/Service_Main.cpp new file mode 100644 index 00000000000..cf20fe799e8 --- /dev/null +++ b/ace/Service_Main.cpp @@ -0,0 +1,37 @@ +// Service_Main.cpp +// $Id$ + +/* This is an example of a canonical Service Configurator daemon's + main() function. Note how this driver file is completely generic + and may be used to configure almost any type of network daemon. */ + +#define ACE_BUILD_DLL +#include "ace/Service_Config.h" + +sig_atomic_t finished = 0; + +static void +handler (int) +{ + ACE_TRACE ("handler"); + finished = 1; +} + +int +sc_main (int argc, char *argv[]) +{ + ACE_TRACE ("sc_main"); + ACE_Service_Config daemon; + + ACE_OS::signal (SIGINT, ACE_SignalHandler (handler)); + + if (daemon.open (argc, argv) == -1) + ACE_ERROR ((LM_ERROR, "%p\n%a", "open", 1)); + + /* Run forever, performing the configured services. */ + + while (!finished) + daemon.run_reactor_event_loop (); + + return 0; +} diff --git a/ace/Service_Manager.cpp b/ace/Service_Manager.cpp new file mode 100644 index 00000000000..2658895e4c6 --- /dev/null +++ b/ace/Service_Manager.cpp @@ -0,0 +1,267 @@ +// Service_Manager.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/Get_Opt.h" +#include "ace/Service_Repository.h" +#include "ace/Service_Config.h" +#include "ace/Service_Manager.h" +#include "ace/Reactor.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Service_Manager.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Manager) + +void +ACE_Service_Manager::dump (void) const +{ + ACE_TRACE ("ACE_Service_Manager::dump"); +} + +/* Static variables. */ + +u_short ACE_Service_Manager::DEFAULT_PORT_ = 10000; + +ACE_Service_Manager::ACE_Service_Manager (void) + : debug_ (0), + signum_ (SIGHUP) +{ + ACE_TRACE ("ACE_Service_Manager::ACE_Service_Manager"); +} + +int +ACE_Service_Manager::suspend (void) +{ + ACE_TRACE ("ACE_Service_Manager::suspend"); + return ACE_Service_Config::reactor ()->suspend_handler (this); +} + +int +ACE_Service_Manager::resume (void) +{ + ACE_TRACE ("ACE_Service_Manager::resume"); + return ACE_Service_Config::reactor ()->resume_handler (this); +} + +int +ACE_Service_Manager::open (const ACE_INET_Addr &sia) +{ + ACE_TRACE ("ACE_Service_Manager::open"); + // Reuse the listening address, even if it's already in use! + if (this->acceptor_.open (sia, 1) == -1) + return -1; + return 0; +} + +int +ACE_Service_Manager::info (char **strp, size_t length) const +{ + ACE_TRACE ("ACE_Service_Manager::info"); + ACE_INET_Addr sa; + char buf[BUFSIZ]; + + if (this->acceptor_.get_local_addr (sa) == -1) + return -1; + + ACE_OS::sprintf (buf, "%d/%s %s", sa.get_port_number (), "tcp", + "# lists all services in the daemon\n"); + + if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, buf, length); + return ACE_OS::strlen (buf); +} + +int +ACE_Service_Manager::init (int argc, char *argv[]) +{ + ACE_TRACE ("ACE_Service_Manager::init"); + ACE_INET_Addr local_addr (ACE_Service_Manager::DEFAULT_PORT_); + ACE_Get_Opt getopt (argc, argv, "dp:s:", 0); // Start at argv[0] + + for (int c; (c = getopt ()) != -1; ) + switch (c) + { + case 'd': + this->debug_ = 1; + break; + case 'p': + local_addr.set (ACE_OS::atoi (getopt.optarg)); + break; + case 's': + this->signum_ = ACE_OS::atoi (getopt.optarg); + break; + default: + break; + } + + if (this->open (local_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); + else if (ACE_Service_Config::reactor ()->register_handler + (this, ACE_Event_Handler::READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "registering service with ACE_Reactor\n"), -1); + return 0; +} + +int +ACE_Service_Manager::handle_close (ACE_HANDLE, ACE_Reactor_Mask) +{ + ACE_TRACE ("ACE_Service_Manager::handle_close"); + return this->acceptor_.close (); +} + +int +ACE_Service_Manager::fini (void) +{ + ACE_TRACE ("ACE_Service_Manager::fini"); + return ACE_Service_Config::reactor ()->remove_handler + (this, ACE_Event_Handler::READ_MASK); +} + +ACE_HANDLE +ACE_Service_Manager::get_handle (void) const +{ + ACE_TRACE ("ACE_Service_Manager::get_handle"); + return this->acceptor_.get_handle (); +} + +int +ACE_Service_Manager::handle_signal (int sig, siginfo_t *, ucontext_t *) +{ + ACE_TRACE ("ACE_Service_Manager::handle_signal"); + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, "got %S\n", sig)); + return 0; +} + +// Determine all the services offered by this daemon and return the +// information back to the client. + +int +ACE_Service_Manager::list_services (void) +{ + ACE_TRACE ("ACE_Service_Manager::list_services"); + ACE_Service_Repository_Iterator sri (*ACE_Service_Config::svc_rep ()); + + for (const ACE_Service_Record *sr; + sri.next (sr) != 0; + sri.advance ()) + { + int len = ACE_OS::strlen (sr->name ()) + 1; + char buf[BUFSIZ], *p = buf + len; + + ACE_OS::strcpy (buf, sr->name ()); + p[-1] = ' '; + p[0] = '\0'; + + len += sr->type ()->info (&p, sizeof buf - len); + + if (this->debug_) + ACE_DEBUG ((LM_DEBUG, "len = %d, info = %s%s", + len, buf, buf[len - 1] == '\n' ? "" : "\n")); + + if (len > 0) + { + ssize_t n = this->client_stream_.send_n (buf, len); + + if (n != len || (n == -1 && errno != EPIPE)) + ACE_ERROR ((LM_ERROR, "%p\n", "send_n")); + } + } + + return 0; +} + +// Trigger a remote reconfiguration of the Service Configurator. + +int +ACE_Service_Manager::reconfigure_services (void) +{ + ACE_TRACE ("ACE_Service_Manager::reconfigure_services"); + +#if 0 +// Send ourselves a signal! ACE_OS::kill (ACE_OS::getpid (), +// this->signum_); +#endif /* 0 */ + + // Flag the main event loop that a reconfiguration should occur. + // The next trip through the ACE_Service_Config::run_reactor_event_loop() + // should pick this up and cause a reconfiguration! + ACE_Service_Config::reconfig_occurred ((sig_atomic_t) 1); + return this->client_stream_.send_n ("done\n", sizeof ("done\n")); +} + +// Accept new connection from client and carry out the service they +// request. + +int +ACE_Service_Manager::handle_input (ACE_HANDLE) +{ + ACE_TRACE ("ACE_Service_Manager::handle_input"); + + if (this->acceptor_.accept (this->client_stream_) == -1) + return -1; + + if (this->debug_) + { + ACE_DEBUG ((LM_DEBUG, "client_stream fd = %d\n", + this->client_stream_.get_handle ())); + ACE_INET_Addr sa; + if (this->client_stream_.get_remote_addr (sa) == -1) + return -1; + + ACE_DEBUG ((LM_DEBUG, "accepted from host %s at port %d\n", + sa.get_host_name (), sa.get_port_number ())); + } + + char request[BUFSIZ]; + + // Read service request from client. + + switch (client_stream_.recv (request, sizeof request)) + { + case -1: + if (this->debug_) + ACE_DEBUG ((LM_ERROR, "%p\n", "recv")); + break; + case 0: + return 0; + /* NOTREACHED */ + default: + { + char *p; + + // Kill trailing newlines. + + for (p = request; + (*p != '\0') && (*p != '\r') && (*p != '\n'); + p++) + continue; + + *p = '\0'; + + ACE_Event_Handler *old_signal_handler = 0; + ACE_Service_Config::reactor ()->register_handler (SIGPIPE, this, 0, + &old_signal_handler); + + if (ACE_OS::strcmp (request, "help") == 0) + this->list_services (); + else if (ACE_OS::strcmp (request, "reconfigure") == 0) + this->reconfigure_services (); + + // Additional management services may be handled here... + + // Restore existing SIGPIPE handler + ACE_Service_Config::reactor ()->register_handler + (SIGPIPE, old_signal_handler); + } + } + if (this->client_stream_.close () == -1 && this->debug_) + ACE_DEBUG ((LM_ERROR, "%p\n", "close")); + + return 0; +} diff --git a/ace/Service_Manager.h b/ace/Service_Manager.h new file mode 100644 index 00000000000..c35b207e759 --- /dev/null +++ b/ace/Service_Manager.h @@ -0,0 +1,74 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Service_Manager.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SERVICE_MANAGER_H) +#define ACE_SERVICE_MANAGER_H + +#include "ace/SOCK_Stream.h" +#include "ace/SOCK_Acceptor.h" +#include "ace/INET_Addr.h" +#include "ace/Service_Object.h" + +class ACE_Export ACE_Service_Manager : public ACE_Service_Object + // = TITLE + // Provide a standard service that returns a list of all services in the + // Service Repository. + // + // = DESCRIPTION + // +{ +public: + ACE_Service_Manager (void); + virtual int list_services (void); + virtual int reconfigure_services (void); + + // = Dynamic linking hooks. + virtual int init (int argc, char *argv[]); + virtual int info (char **info_string, size_t length) const; + virtual int fini (void); + + // = Scheduling hooks. + virtual int suspend (void); + virtual int resume (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int open (const ACE_INET_Addr &sia); + + // = Demultiplexing hooks. + virtual ACE_HANDLE get_handle (void) const; + virtual int handle_input (ACE_HANDLE fd); + virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask); + virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); + + ACE_SOCK_Stream client_stream_; + ACE_SOCK_Acceptor acceptor_; + int debug_; + int signum_; + static u_short DEFAULT_PORT_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Service_Manager.i" +#endif /* __ACE_INLINE__ */ + +#endif /* _SERVICE_MANAGER_H */ diff --git a/ace/Service_Manager.i b/ace/Service_Manager.i new file mode 100644 index 00000000000..e4bcf581ee0 --- /dev/null +++ b/ace/Service_Manager.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Service_Manager.i diff --git a/ace/Service_Object.cpp b/ace/Service_Object.cpp new file mode 100644 index 00000000000..e0defc425a7 --- /dev/null +++ b/ace/Service_Object.cpp @@ -0,0 +1,71 @@ +// Service_Object.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Service_Object.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Service_Object.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Object) + +/* Provide the abstract base class common to all services */ + +ACE_Service_Object::ACE_Service_Object (void) +{ + ACE_TRACE ("ACE_Service_Object::ACE_Service_Object"); +} + +ACE_Service_Object::~ACE_Service_Object (void) +{ + ACE_TRACE ("ACE_Service_Object::~ACE_Service_Object"); +} + +int +ACE_Service_Object::suspend (void) +{ + ACE_TRACE ("ACE_Service_Object::suspend"); + return 0; +} + +int +ACE_Service_Object::resume (void) +{ + ACE_TRACE ("ACE_Service_Object::resume"); + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Type) + +void +ACE_Service_Type::dump (void) const +{ + ACE_TRACE ("ACE_Service_Type::dump"); +} + +ACE_Service_Type::ACE_Service_Type (const void *so, + const char *s_name, + unsigned int f) + : obj_ (so), + flags_ (f) +{ + ACE_TRACE ("ACE_Service_Type::ACE_Service_Type"); + this->name (ACE_OS::strcpy (new char[::strlen (s_name) + 1], s_name)); +} + +int +ACE_Service_Type::fini (void) const +{ + ACE_TRACE ("ACE_Service_Type::fini"); + ACE_DEBUG ((LM_DEBUG, "destroying %s, flags = %d\n", + this->name_, this->flags_)); + + delete [] (char *) this->name_; + if (ACE_BIT_ENABLED (this->flags_, ACE_Service_Type::DELETE_OBJ)) + delete (void *) this->object (); + if (ACE_BIT_ENABLED (this->flags_, ACE_Service_Type::DELETE_THIS)) + delete (void *) this; // Prevent object's destructor from being called... + return 0; +} + diff --git a/ace/Service_Object.h b/ace/Service_Object.h new file mode 100644 index 00000000000..32624e21a4e --- /dev/null +++ b/ace/Service_Object.h @@ -0,0 +1,94 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Service_Object.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SERVICE_OBJECT_H) +#define ACE_SERVICE_OBJECT_H + +#include "ace/Shared_Object.h" +#include "ace/Event_Handler.h" +#include "ace/Log_Msg.h" + +class ACE_Export ACE_Service_Object : public ACE_Event_Handler, public ACE_Shared_Object + // = TITLE + // Provide the abstract base class common to all services +{ +public: + // = Initialization and termination methods. + ACE_Service_Object (void); + virtual ~ACE_Service_Object (void); + + virtual int suspend (void); + // Temporarily disable a service without removing it completely + virtual int resume (void); + // Re-enable a previously suspended service +}; + +class ACE_Export ACE_Service_Type + // = TITLE + // Provide the class hierarchy that defines the contents of + // the Service Repository search structure. +{ +public: + enum + { + DELETE_OBJ = 1, // Delete the payload object. + DELETE_THIS = 2 // Delete the enclosing object. + }; + + // = Initialization method. + ACE_Service_Type (const void *object, + const char *s_name, + u_int flags = 0); + + // = Pure virtual interface (must be defined by the subclass). + virtual int suspend (void) const = 0; + virtual int resume (void) const = 0; + virtual int init (int argc, char *argv[]) const = 0; + virtual int fini (void) const; + virtual int info (char **str, size_t len) const = 0; + + const void *object (void) const; + // The pointer to the service. + + const char *name (void) const; + // Get the name of the service. + + void name (const char *); + // Set the name of the service. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + const char *name_; + // Name of the service. + + const void *obj_; + // Pointer to object that implements the service. + + u_int flags_; + // Flags that control serivce behavior (particularly deletion). +}; + +#if defined (__ACE_INLINE__) +#include "ace/Service_Object.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SERVICE_OBJECT_H */ diff --git a/ace/Service_Object.i b/ace/Service_Object.i new file mode 100644 index 00000000000..530757b6363 --- /dev/null +++ b/ace/Service_Object.i @@ -0,0 +1,26 @@ +/* -*- C++ -*- */ +// $Id$ + +// Service_Object.i + +ACE_INLINE const void * +ACE_Service_Type::object (void) const +{ + ACE_TRACE ("ACE_Service_Type::object"); + return this->obj_; +} + +ACE_INLINE const char * +ACE_Service_Type::name (void) const +{ + ACE_TRACE ("ACE_Service_Type::name"); + return this->name_; +} + +ACE_INLINE void +ACE_Service_Type::name (const char *n) +{ + ACE_TRACE ("ACE_Service_Type::name"); + this->name_ = n; +} + diff --git a/ace/Service_Record.cpp b/ace/Service_Record.cpp new file mode 100644 index 00000000000..b4b8dccbf65 --- /dev/null +++ b/ace/Service_Record.cpp @@ -0,0 +1,340 @@ +// Service_Record.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Service_Record.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Service_Record.i" +#endif /* __ACE_INLINE__ */ + +ACE_Service_Object_Type::ACE_Service_Object_Type (ACE_Service_Object *so, + const char *s_name, + unsigned int f) + : ACE_Service_Type ((const void *) so, s_name, f) +{ + ACE_TRACE ("ACE_Service_Object_Type::ACE_Service_Object_Type"); +} + +int +ACE_Service_Object_Type::init (int argc, char *argv[]) const +{ + ACE_TRACE ("ACE_Service_Object_Type::init"); + const void *obj = this->object (); + ACE_Service_Object *so = (ACE_Service_Object *) obj; + + if (so == 0) + return -1; + else + return so->init (argc, argv); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Module_Type) + +void +ACE_Module_Type::dump (void) const +{ + ACE_TRACE ("ACE_Module_Type::dump"); +} + +ACE_Module_Type::ACE_Module_Type (MT_Module *m, + const char *m_name, + u_int f) + : ACE_Service_Type ((const void *) m, m_name, f) +{ + ACE_TRACE ("ACE_Module_Type::ACE_Module_Type"); +} + +int +ACE_Module_Type::init (int argc, char *argv[]) const +{ + ACE_TRACE ("ACE_Module_Type::init"); + const void *obj = this->object (); + MT_Module *mod = (MT_Module *) obj; + MT_Task *reader = mod->reader (); + MT_Task *writer = mod->writer (); + + if (reader->init (argc, argv) == -1 + || writer->init (argc, argv) == -1) + return -1; + else + return 0; +} + +int +ACE_Module_Type::suspend (void) const +{ + ACE_TRACE ("ACE_Module_Type::suspend"); + const void *obj = this->object (); + MT_Module *mod = (MT_Module *) obj; + MT_Task *reader = mod->reader (); + MT_Task *writer = mod->writer (); + + if (reader->suspend () == -1 + || writer->suspend () == -1) + return -1; + else + return 0; +} + +int +ACE_Module_Type::resume (void) const +{ + ACE_TRACE ("ACE_Module_Type::resume"); + const void *obj = this->object (); + MT_Module *mod = (MT_Module *) obj; + MT_Task *reader = mod->reader (); + MT_Task *writer = mod->writer (); + + if (reader->resume () == -1 + || writer->resume () == -1) + return -1; + else + return 0; +} + +// Note, these operations are somewhat too familiar with the +// implementation of ACE_Module and ACE_Module::close... + +int +ACE_Module_Type::fini (void) const +{ + ACE_TRACE ("ACE_Module_Type::fini"); + const void *obj = this->object (); + MT_Module *mod = (MT_Module *) obj; + MT_Task *reader = mod->reader (); + MT_Task *writer = mod->writer (); + + reader->fini (); + writer->fini (); + delete reader; + delete writer; + return ACE_Service_Type::fini (); +} + +int +ACE_Module_Type::info (char **str, size_t len) const +{ + ACE_TRACE ("ACE_Module_Type::info"); + char buf[BUFSIZ]; + + ACE_OS::sprintf (buf, "%s\t %s", this->name (), "# ACE_Module\n"); + + if (*str == 0 && (*str = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*str, buf, len); + return ACE_OS::strlen (buf); +} + +void +ACE_Module_Type::link (ACE_Module_Type *n) +{ + ACE_TRACE ("ACE_Module_Type::link"); + this->next_ = n; +} + +ACE_Module_Type * +ACE_Module_Type::link (void) const +{ + ACE_TRACE ("ACE_Module_Type::link"); + return this->next_; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Type) + +void +ACE_Stream_Type::dump (void) const +{ + ACE_TRACE ("ACE_Stream_Type::dump"); +} + +int +ACE_Stream_Type::init (int, char *[]) const +{ + ACE_TRACE ("ACE_Stream_Type::init"); + return 0; +} + +int +ACE_Stream_Type::suspend (void) const +{ + ACE_TRACE ("ACE_Stream_Type::suspend"); + for (ACE_Module_Type *m = this->head_; m != 0; m = m->link ()) + m->suspend (); + + return 0; +} + +int +ACE_Stream_Type::resume (void) const +{ + ACE_TRACE ("ACE_Stream_Type::resume"); + for (ACE_Module_Type *m = this->head_; m != 0; m = m->link ()) + m->resume (); + + return 0; +} + +ACE_Stream_Type::ACE_Stream_Type (MT_Stream *s, + const char *s_name, + unsigned int f) + : ACE_Service_Type ((const void *) s, s_name, f), + head_ (0) +{ + ACE_TRACE ("ACE_Stream_Type::ACE_Stream_Type"); +} + +int +ACE_Stream_Type::info (char **str, size_t len) const +{ + ACE_TRACE ("ACE_Stream_Type::info"); + char buf[BUFSIZ]; + + ACE_OS::sprintf (buf, "%s\t %s", this->name (), "# STREAM\n"); + + if (*str == 0 && (*str = ACE_OS::strdup (buf)) == 0) + return -1; + else + ACE_OS::strncpy (*str, buf, len); + return ACE_OS::strlen (buf); +} + +int +ACE_Stream_Type::fini (void) const +{ + ACE_TRACE ("ACE_Stream_Type::fini"); + const void *obj = this->object (); + MT_Stream *str = (MT_Stream *) obj; + + for (ACE_Module_Type *m = this->head_; m != 0; ) + { + ACE_Module_Type *t = m->link (); + + // Final 0 arg disables ACE_Module::DELETE_THIS + str->remove (m->name (), 0); + m->fini (); + m = t; + } + + str->close (); + return ACE_Service_Type::fini (); +} + +// Locate and remove MOD_NAME from the ACE_Stream. + +int +ACE_Stream_Type::remove (ACE_Module_Type *mod) +{ + ACE_TRACE ("ACE_Stream_Type::remove"); + ACE_Module_Type *prev = 0; + const void *obj = this->object (); + MT_Stream *str = (MT_Stream *) obj; + int result = 0; + + ACE_Module_Type *m = this->head_; + + while (m != 0) + { + ACE_Module_Type *next = m->link (); + // We need to do this first so we don't bomb out if we delete m! + + if (m == mod) + { + if (prev == 0) + this->head_ = next; + else + prev->link (next); + + // Final 0 arg disables ACE_Module::DELETE_THIS + if (str->remove (m->name (), 0) == -1) + result = -1; + m->fini (); // This call may end up deleteing m! + } + else + prev = m; + + m = next; + } + + return result; +} + +int +ACE_Stream_Type::push (ACE_Module_Type *new_module) +{ + ACE_TRACE ("ACE_Stream_Type::push"); + const void *obj = this->object (); + MT_Stream *str = (MT_Stream *) obj; + + new_module->link (this->head_); + this->head_ = new_module; + obj = new_module->object (); + return str->push ((MT_Module *) obj); +} + +ACE_Module_Type * +ACE_Stream_Type::find (const char *mod_name) const +{ + ACE_TRACE ("ACE_Stream_Type::find"); + for (ACE_Module_Type *m = this->head_; m != 0; m = m->link ()) + if (ACE_OS::strcmp (m->name (), mod_name) == 0) + return m; + + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Record) + +void +ACE_Service_Record::dump (void) const +{ + ACE_TRACE ("ACE_Service_Record::dump"); +} + +ACE_Service_Record::ACE_Service_Record (const char *n, + ACE_Service_Type *t, + const void *h, + int active) + : type_ (t), handle_ (h), active_ (active) +{ + ACE_TRACE ("ACE_Service_Record::ACE_Service_Record"); + this->name (n); +} + +ACE_Service_Record::~ACE_Service_Record (void) +{ + ACE_TRACE ("ACE_Service_Record::~ACE_Service_Record"); + this->type_->fini (); + if (this->handle_ != 0) + ACE_OS::dlclose ((void *) this->handle_); + delete [] (char *) this->name_; +} + +void +ACE_Service_Record::suspend (void) const +{ + ACE_TRACE ("ACE_Service_Record::suspend"); + ((ACE_Service_Record *) this)->active_ = 0; + this->type_->suspend (); +} + +void +ACE_Service_Record::resume (void) const +{ + ACE_TRACE ("ACE_Service_Record::resume"); + ((ACE_Service_Record *) this)->active_ = 1; + this->type_->resume (); +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Module<ACE_SYNCH>; +template class ACE_Stream<ACE_SYNCH>; +template class ACE_Task<ACE_SYNCH>; +template class ACE_Message_Queue<ACE_SYNCH>; +template class ACE_Task_Exit<ACE_SYNCH>; +template class ACE_TSS<ACE_Task_Exit<ACE_SYNCH> >; +template class ACE_Thru_Task<ACE_SYNCH>; +template class ACE_Stream_Head<ACE_SYNCH>; +template class ACE_Stream_Tail<ACE_SYNCH>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Service_Record.h b/ace/Service_Record.h new file mode 100644 index 00000000000..427969d2b04 --- /dev/null +++ b/ace/Service_Record.h @@ -0,0 +1,153 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Service_Record.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SERVICE_RECORD_H) +#define ACE_SERVICE_RECORD_H + +#include "ace/Service_Object.h" +#include "ace/Synch.h" +#include "ace/Stream.h" + +typedef ACE_Stream<ACE_SYNCH> MT_Stream; +typedef ACE_Module<ACE_SYNCH> MT_Module; +typedef ACE_Task<ACE_SYNCH> MT_Task; + +class ACE_Export ACE_Service_Object_Type : public ACE_Service_Type + // = TITLE + // Define the methods for handling <ACE_Service_Objects>. +{ +public: + ACE_Service_Object_Type (ACE_Service_Object *so, + const char *name, + u_int flags = 0); + virtual int suspend (void) const; + virtual int resume (void) const; + virtual int init (int argc, char *argv[]) const; + virtual int fini (void) const; + virtual int info (char **str, size_t len) const; +}; + +class ACE_Export ACE_Module_Type : public ACE_Service_Type + // = TITLE + // Define the methods for handling <ACE_Modules>. +{ +public: + ACE_Module_Type (MT_Module *m, + const char *identifier, + u_int flags = 0); + + virtual int suspend (void) const; + virtual int resume (void) const; + virtual int init (int argc, char *argv[]) const; + virtual int fini (void) const; + virtual int info (char **str, size_t len) const; + + ACE_Module_Type *link (void) const; + void link (ACE_Module_Type *); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Module_Type *next_; +}; + +class ACE_Export ACE_Stream_Type : public ACE_Service_Type + // = TITLE + // Define the methods for handling <ACE_Streams>. +{ +public: + ACE_Stream_Type (MT_Stream *s, + const char *identifier, + u_int flags = 0); + + virtual int suspend (void) const; + virtual int resume (void) const; + virtual int init (int argc, char *argv[]) const; + virtual int fini (void) const; + virtual int info (char **str, size_t len) const; + + int push (ACE_Module_Type *new_module); + int remove (ACE_Module_Type *module); + ACE_Module_Type *find (const char *mod_name) const; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Module_Type *head_; +}; + +class ACE_Export ACE_Service_Record + // = TITLE + // Packaging interface for the various types of + // <ACE_Service_Types>. +{ +public: + // = Initialization and termination methods. + ACE_Service_Record (const char *n, + ACE_Service_Type *o, + const void *handle, + int active); + ~ACE_Service_Record (void); + + const char *name (void) const; + void name (const char *); + + const ACE_Service_Type *type (void) const; + void type (const ACE_Service_Type *, + int active = 1); + + const void *handle (void) const; + void handle (const void *); + + void suspend (void) const; + void resume (void) const; + int active (void) const; + void active (int); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const char *name_; + // Humanly readible name of svc. + + const ACE_Service_Type *type_; + // Pointer to C++ object that implements the svc. + + const void *handle_; + // Handle to shared object file (non-zero if dynamically linked). + + int active_; + // 1 if svc is currently active, otherwise 0. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Service_Record.i" +#endif /* __ACE_INLINE__ */ + +#endif /* _SERVICE_RECORD_H */ diff --git a/ace/Service_Record.i b/ace/Service_Record.i new file mode 100644 index 00000000000..bd6d667a593 --- /dev/null +++ b/ace/Service_Record.i @@ -0,0 +1,91 @@ +/* -*- C++ -*- */ +// $Id$ + +// Service_Record.i + +ACE_INLINE int +ACE_Service_Object_Type::suspend (void) const +{ + ACE_TRACE ("ACE_Service_Object_Type::suspend"); + return ((ACE_Service_Object *) this->object ())->suspend (); +} + +ACE_INLINE int +ACE_Service_Object_Type::resume (void) const +{ + ACE_TRACE ("ACE_Service_Object_Type::resume"); + return ((ACE_Service_Object *) this->object ())->resume (); +} + +ACE_INLINE int +ACE_Service_Object_Type::fini (void) const +{ + ACE_TRACE ("ACE_Service_Object_Type::fini"); + ACE_Service_Object *so = (ACE_Service_Object *) this->object (); + so->fini (); + return ACE_Service_Type::fini (); +} + +ACE_INLINE int +ACE_Service_Object_Type::info (char **str, size_t len) const +{ + ACE_TRACE ("ACE_Service_Object_Type::info"); + return ((ACE_Service_Object *) this->object ())->info (str, len); +} + +ACE_INLINE const char * +ACE_Service_Record::name (void) const +{ + ACE_TRACE ("ACE_Service_Record::name"); + return this->name_; +} + +ACE_INLINE const ACE_Service_Type * +ACE_Service_Record::type (void) const +{ + ACE_TRACE ("ACE_Service_Record::type"); + return this->type_; +} + +ACE_INLINE const void * +ACE_Service_Record::handle (void) const +{ + ACE_TRACE ("ACE_Service_Record::handle"); + return this->handle_; +} + +ACE_INLINE void +ACE_Service_Record::name (const char *n) +{ + ACE_TRACE ("ACE_Service_Record::name"); + this->name_ = ACE_OS::strcpy (new char [::strlen (n) + 1], n); +} + +ACE_INLINE void +ACE_Service_Record::type (const ACE_Service_Type *o, int enabled) +{ + ACE_TRACE ("ACE_Service_Record::type"); + this->type_ = o; + ((ACE_Service_Record *) this)->active_ = enabled; +} + +ACE_INLINE void +ACE_Service_Record::handle (const void *h) +{ + ACE_TRACE ("ACE_Service_Record::handle"); + this->handle_ = h; +} + +ACE_INLINE int +ACE_Service_Record::active (void) const +{ + ACE_TRACE ("ACE_Service_Record::active"); + return this->active_ != 0; +} + +ACE_INLINE void +ACE_Service_Record::active (int turnon) +{ + ACE_TRACE ("ACE_Service_Record::active"); + this->active_ = turnon; +} diff --git a/ace/Service_Repository.cpp b/ace/Service_Repository.cpp new file mode 100644 index 00000000000..24af60fd277 --- /dev/null +++ b/ace/Service_Repository.cpp @@ -0,0 +1,281 @@ +// Service_Repository.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Service_Repository.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Service_Repository.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Repository) + +void +ACE_Service_Repository::dump (void) const +{ + ACE_TRACE ("ACE_Service_Repository::dump"); +} + +ACE_Service_Repository::ACE_Service_Repository (void) + : current_size_ (0), + total_size_ (0), + service_vector_ (0) +{ + ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository"); +} + +// Initialize the Repository to a clean slate. + +int +ACE_Service_Repository::open (int size) +{ + ACE_TRACE ("ACE_Service_Repository::open"); + + this->total_size_ = size; + this->service_vector_ = + (const ACE_Service_Record **) new ACE_Service_Record *[size]; + if (this->service_vector_ == 0) + { + errno = ENOMEM; + return -1; + } + + return 0; +} + +ACE_Service_Repository::ACE_Service_Repository (int size) + : current_size_ (0) +{ + ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository"); + + if (this->open (size) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Service_Repository")); +} + +/* Close down all the services */ + +int +ACE_Service_Repository::close (void) +{ + ACE_TRACE ("ACE_Service_Repository::close"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + + if (this->service_vector_ != 0) + { + for (int i = 0; i < this->current_size_; i++) + { + ACE_DEBUG ((LM_DEBUG, "shutting down %s\n", + this->service_vector_[i]->name ())); + delete (ACE_Service_Record *) this->service_vector_[i]; + } + + delete [] this->service_vector_; + this->service_vector_ = 0; + this->current_size_ = 0; + } + return 0; +} + +ACE_Service_Repository::~ACE_Service_Repository (void) +{ + ACE_TRACE ("ACE_Service_Repository::~ACE_Service_Repository"); + this->close (); +} + +// Locate an entry with NAME in the table. If IGNORE_SUSPENDED is set +// then only consider services marked as resumed. If the caller wants +// the located entry, pass back a pointer to the located entry via +// SRP. If NAME is not found -1 is returned. If NAME is found, but +// it is suspended and the caller wants to ignore suspended services a +// -2 is returned. Must be called with locks held. + +int +ACE_Service_Repository::find_i (const char name[], + const ACE_Service_Record **srp, + int ignore_suspended) +{ + ACE_TRACE ("ACE_Service_Repository::find_i"); + int i; + + for (i = 0; i < this->current_size_; i++) + if (ACE_OS::strcmp (name, this->service_vector_[i]->name ()) == 0) + break; + + if (i < this->current_size_) + { + if (srp != 0) + *srp = this->service_vector_[i]; + if (ignore_suspended && this->service_vector_[i]->active () == 0) + return -2; + return i; + } + else + return -1; +} + +int +ACE_Service_Repository::find (const char name[], + const ACE_Service_Record **srp, + int ignore_suspended) +{ + ACE_TRACE ("ACE_Service_Repository::find"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + + return this->find_i (name, srp, ignore_suspended); +} + + +// Insert the ACE_Service_Record SR into the repository. Note that +// services may be inserted either resumed or suspended. + +int +ACE_Service_Repository::insert (const ACE_Service_Record *sr) +{ + ACE_TRACE ("ACE_Service_Repository::insert"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + int i; + + for (i = 0; i < this->current_size_; i++) + if (ACE_OS::strcmp (sr->name (), + this->service_vector_[i]->name ()) == 0) + break; + + if (i < this->current_size_) // Replacing an existing entry + { + // Check for self-assignment... + if (sr == this->service_vector_[i]) + return 0; + delete (ACE_Service_Record *) this->service_vector_[i]; + this->service_vector_[i] = sr; + return 0; + } + else if (i < this->total_size_) // Adding a new entry. + { + this->service_vector_[i] = sr; + this->current_size_++; + return 0; + } + else + return -1; +} + +// Re-resume a service that was previously suspended. + +int +ACE_Service_Repository::resume (const char name[], + const ACE_Service_Record **srp) +{ + ACE_TRACE ("ACE_Service_Repository::resume"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + + int i = this->find_i (name, srp, 0); + + if (i == -1) + return -1; + + this->service_vector_[i]->resume (); + return 0; +} + +// Suspend a service so that it will not be considered active under +// most circumstances by other portions of the ACE_Service_Repository. + +int +ACE_Service_Repository::suspend (const char name[], + const ACE_Service_Record **srp) +{ + ACE_TRACE ("ACE_Service_Repository::suspend"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + int i = this->find_i (name, srp, 0); + + if (i == -1) + return -1; + + this->service_vector_[i]->suspend (); + return 0; +} + +// Completely remove a <name> entry from the Repository and +// dynamically unlink it if it was originally dynamically linked. +// Since the order of services in the Respository does not matter, we +// simply overwrite the entry being deleted with the final entry in +// the array and decrement the <service_count> by 1. + +int +ACE_Service_Repository::remove (const char name[]) +{ + ACE_TRACE ("ACE_Service_Repository::remove"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + int i = this->find_i (name, 0, 0); + + if (i == -1) + return -1; + else + { + const void *handle = this->service_vector_[i]->handle (); + delete (ACE_Service_Record *) this->service_vector_[i]; + + if (handle != 0) + ACE_OS::dlclose ((void *) handle); + + if (--this->current_size_ > 1) + this->service_vector_[i] + = this->service_vector_[this->current_size_]; + return 0; + } +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Service_Repository_Iterator) + +void +ACE_Service_Repository_Iterator::dump (void) const +{ + ACE_TRACE ("ACE_Service_Repository_Iterator::dump"); +} + +// Initializes the iterator and skips over any suspended entries at +// the beginning of the table, if necessary. Note, you must not +// perform destructive operations on elements during this iteration... + +ACE_Service_Repository_Iterator::ACE_Service_Repository_Iterator + (ACE_Service_Repository &sr, int ignr_suspended) + : svc_rep_ (sr), + next_ (-1), + ignore_suspended_ (ignr_suspended) +{ + this->advance (); +} + +// Obtains a pointer to the next valid service in the table. If there +// are no more entries, returns 0, else 1. + +int +ACE_Service_Repository_Iterator::next (const ACE_Service_Record *&sr) +{ + ACE_TRACE ("ACE_Service_Repository_Iterator::next"); + if (this->next_ < this->svc_rep_.current_size_) + { + sr = this->svc_rep_.service_vector_[this->next_]; + return 1; + } + else + return 0; +} + +// Advance the iterator by the proper amount. If we are ignoring +// suspended entries and the current entry is suspended, then we must +// skip over this entry. Otherwise, we must advance the NEXT index to +// reference the next valid service entry. + +int +ACE_Service_Repository_Iterator::advance (void) +{ + ACE_TRACE ("ACE_Service_Repository_Iterator::advance"); + for (++this->next_; + this->next_ < this->svc_rep_.current_size_ + && this->ignore_suspended_ + && this->svc_rep_.service_vector_[this->next_]->active () == 0; + this->next_++) + continue; + return this->next_; +} diff --git a/ace/Service_Repository.h b/ace/Service_Repository.h new file mode 100644 index 00000000000..2d758e1ffe3 --- /dev/null +++ b/ace/Service_Repository.h @@ -0,0 +1,130 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Service_Repository.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SERVICE_REPOSITORY_H) +#define ACE_SERVICE_REPOSITORY_H + +#include "ace/Service_Record.h" + +class ACE_Export ACE_Service_Repository + // = TITLE + // Provide the abstract base class that supplies common server + // repository operations. +{ +public: + enum {DEFAULT_SIZE = 50}; + // = Initialization and termination methods. + ACE_Service_Repository (void); + // Initialize the repository. + + ACE_Service_Repository (int size); + // Initialize the repository. + + int open (int size = DEFAULT_SIZE); + // Initialize the repository. + + ~ACE_Service_Repository (void); + // Terminate the repository. + + int close (void); + // Terminate the repository. + + // = Search structure operations (all acquire locks as necessary). + + int insert (const ACE_Service_Record *); + // Insert a new service record. + + int find (const char[], + const ACE_Service_Record ** = 0, + int ignore_suspended = 1); + // Locate an existing service record. + + int remove (const char[]); + // Remove an existing service record. + + // = Liveness control + int resume (const char[], const ACE_Service_Record ** = 0); + // Resume a service record. + + int suspend (const char[], const ACE_Service_Record ** = 0); + // Suspend a service record. + + int current_size (void); + // Return the current size of the repository. + + int total_size (void); + // Return the total size of the repository. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int find_i (const char service_name[], + const ACE_Service_Record ** = 0, + int ignore_suspended = 1); + // Locates <service_name>. Must be called without locks being + // held... + + const ACE_Service_Record **service_vector_; + // Contains all the configured services. + + int current_size_; + // Current number of services. + + int total_size_; + // Maximum number of service. + +#if defined (ACE_MT_SAFE) + ACE_Thread_Mutex lock_; + // Synchronization variable for the MT_SAFE Repository +#endif /* ACE_MT_SAFE */ + + friend class ACE_Service_Repository_Iterator; +}; + +class ACE_Export ACE_Service_Repository_Iterator + // = TITLE + // + // = DESCRIPTION + // +{ +public: + ACE_Service_Repository_Iterator (ACE_Service_Repository &sr, + int ignored_suspended = 1); + int next (const ACE_Service_Record *&so); + int advance (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Service_Repository &svc_rep_; + int next_; + int ignore_suspended_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Service_Repository.i" +#endif /* __ACE_INLINE__ */ + +#endif /* _SERVICE_REPOSITORY_H */ diff --git a/ace/Service_Repository.i b/ace/Service_Repository.i new file mode 100644 index 00000000000..d5b70714154 --- /dev/null +++ b/ace/Service_Repository.i @@ -0,0 +1,27 @@ +/* -*- C++ -*- */ +// $Id$ + +// Service_Repository.i + +// Returns a count of the number of currently valid entries (counting +// both resumed and suspended entries). + +ACE_INLINE int +ACE_Service_Repository::current_size (void) +{ + ACE_TRACE ("ACE_Service_Repository::current_size"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + return this->current_size_; +} + +// Returns a count of the total number of possible entries in the +// table. + +ACE_INLINE int +ACE_Service_Repository::total_size (void) +{ + ACE_TRACE ("ACE_Service_Repository::total_size"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + return this->total_size_; +} + diff --git a/ace/Set.cpp b/ace/Set.cpp new file mode 100644 index 00000000000..85d5568149d --- /dev/null +++ b/ace/Set.cpp @@ -0,0 +1,502 @@ +// Set.cpp +// $Id$ + +#if !defined (ACE_SET_C) +#define ACE_SET_C + +#define ACE_BUILD_DLL +#include "ace/Set.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Set.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Set) + +template <class T, size_t SIZE> void +ACE_Fixed_Set<T, SIZE>::dump (void) const +{ + ACE_TRACE ("ACE_Fixed_Set<T, SIZE>::dump"); +} + +template <class T, size_t SIZE> +ACE_Fixed_Set<T, SIZE>::~ACE_Fixed_Set (void) +{ + ACE_TRACE ("ACE_Fixed_Set<T, SIZE>::~ACE_Fixed_Set"); + this->cur_size_ = 0; +} + +template <class T, size_t SIZE> +ACE_Fixed_Set<T, SIZE>::ACE_Fixed_Set (void) + : cur_size_ (0), + max_size_ (SIZE) +{ + ACE_TRACE ("ACE_Fixed_Set<T, SIZE>::ACE_Fixed_Set"); + for (size_t i = 0; i < this->max_size_; i++) + this->search_structure_[i].is_free_ = 1; +} + +template <class T, size_t SIZE> int +ACE_Fixed_Set<T, SIZE>::find (const T &item) const +{ + ACE_TRACE ("ACE_Fixed_Set<T, SIZE>::find"); + for (size_t i = 0; i < this->cur_size_; i++) + { + if (this->search_structure_[i].item_ == item + && this->search_structure_[i].is_free_ == 0) + return 1; + } + + return 0; +} + +template <class T, size_t SIZE> int +ACE_Fixed_Set<T, SIZE>::insert (const T &item) + +{ + ACE_TRACE ("ACE_Fixed_Set<T, SIZE>::insert"); + int first_free = -1; // Keep track of first free slot. + size_t i; + + for (i = 0; i < this->cur_size_; i++) + { + // First, make sure we don't allow duplicates. + + if (this->search_structure_[i].item_ == item + && this->search_structure_[i].is_free_ == 0) + return 1; + else if (this->search_structure_[i].is_free_ + && first_free == -1) + first_free = i; + } + + // If we found a free spot let's reuse it. + if (first_free > -1) + { + this->search_structure_[first_free].item_ = item; + this->search_structure_[first_free].is_free_ = 0; + return 0; + } + // Insert at the end of the active portion. + else if (i < this->max_size_) + { + this->search_structure_[i].item_ = item; + this->search_structure_[i].is_free_ = 0; + this->cur_size_++; + return 0; + } + else /* No more room! */ + { + errno = ENOMEM; + return -1; + } +} + +template <class T, size_t SIZE> int +ACE_Fixed_Set<T, SIZE>::remove (const T &item) +{ + ACE_TRACE ("ACE_Fixed_Set<T, SIZE>::remove"); + for (size_t i = 0; i < this->cur_size_; i++) + { + if (this->search_structure_[i].item_ == item) + { + size_t index = i; + + // Mark this entry as being free. + this->search_structure_[i].is_free_ = 1; + + // If we just unbound the highest entry, then we need to + // figure out where the next highest active entry is. + if (i + 1 == this->cur_size_) + { + while (i > 0 + && this->search_structure_[--i].is_free_) + continue; + + if (i == 0 + && this->search_structure_[i].is_free_) + this->cur_size_ = 0; + else + this->cur_size_ = i + 1; + } + return 1; + } + } + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Set_Iterator) + +template <class T, size_t SIZE> void +ACE_Fixed_Set_Iterator<T, SIZE>::dump (void) const +{ + ACE_TRACE ("ACE_Fixed_Set_Iterator<T, SIZE>::dump"); +} + +template <class T, size_t SIZE> +ACE_Fixed_Set_Iterator<T, SIZE>::ACE_Fixed_Set_Iterator (ACE_Fixed_Set<T, SIZE> &s) + : s_ (s), + next_ (-1) +{ + ACE_TRACE ("ACE_Fixed_Set_Iterator<T, SIZE>::ACE_Fixed_Set_Iterator"); + this->advance (); +} + +template <class T, size_t SIZE> int +ACE_Fixed_Set_Iterator<T, SIZE>::advance (void) +{ + ACE_TRACE ("ACE_Fixed_Set_Iterator<T, SIZE>::advance"); + for (++this->next_; + size_t (this->next_) < this->s_.cur_size_ + && this->s_.search_structure_[this->next_].is_free_; + ++this->next_) + continue; + + return this->next_; +} + +template <class T, size_t SIZE> int +ACE_Fixed_Set_Iterator<T, SIZE>::next (T *&item) +{ + ACE_TRACE ("ACE_Fixed_Set_Iterator<T, SIZE>::next"); + if (size_t (this->next_) < this->s_.cur_size_) + { + item = &this->s_.search_structure_[this->next_].item_; + return 1; + } + else + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Set) + +template <class T> void +ACE_Bounded_Set<T>::dump (void) const +{ + ACE_TRACE ("ACE_Bounded_Set<T>::dump"); +} + +template <class T> +ACE_Bounded_Set<T>::~ACE_Bounded_Set (void) +{ + ACE_TRACE ("ACE_Bounded_Set<T>::~ACE_Bounded_Set"); + delete [] this->search_structure_; +} + +template <class T> +ACE_Bounded_Set<T>::ACE_Bounded_Set (void) + : cur_size_ (0), + max_size_ (size_t (ACE_Bounded_Set<T>::DEFAULT_SIZE)) +{ + ACE_TRACE ("ACE_Bounded_Set<T>::ACE_Bounded_Set"); + + ACE_NEW (this->search_structure_, ACE_Bounded_Set<T>::Search_Structure[this->max_size_]); + + for (size_t i = 0; i < this->max_size_; i++) + this->search_structure_[i].is_free_ = 1; +} + +template <class T> +ACE_Bounded_Set<T>::ACE_Bounded_Set (size_t size) + : cur_size_ (0), + max_size_ (size) +{ + ACE_TRACE ("ACE_Bounded_Set<T>::ACE_Bounded_Set"); + ACE_NEW (this->search_structure_, ACE_Bounded_Set<T>::Search_Structure[size]); + + for (size_t i = 0; i < this->max_size_; i++) + this->search_structure_[i].is_free_ = 1; +} + +template <class T> int +ACE_Bounded_Set<T>::find (const T &item) const +{ + ACE_TRACE ("ACE_Bounded_Set<T>::find"); + for (size_t i = 0; i < this->cur_size_; i++) + { + if (this->search_structure_[i].item_ == item + && this->search_structure_[i].is_free_ == 0) + return 1; + } + + return 0; +} + +template <class T> int +ACE_Bounded_Set<T>::insert (const T &item) +{ + ACE_TRACE ("ACE_Bounded_Set<T>::insert"); + int first_free = -1; // Keep track of first free slot. + size_t i; + + for (i = 0; i < this->cur_size_; i++) + { + // First, make sure we don't allow duplicates. + + if (this->search_structure_[i].item_ == item + && this->search_structure_[i].is_free_ == 0) + return 1; + else if (this->search_structure_[i].is_free_ && first_free == -1) + first_free = i; + } + + if (first_free > -1) // If we found a free spot let's reuse it. + { + this->search_structure_[first_free].item_ = item; + this->search_structure_[first_free].is_free_ = 0; + return 0; + } + else if (i < this->max_size_) // Insert at the end of the active portion. + { + this->search_structure_[i].item_ = item; + this->search_structure_[i].is_free_ = 0; + this->cur_size_++; + return 0; + } + else /* No more room! */ + { + errno = ENOMEM; + return -1; + } +} + +template <class T> int +ACE_Bounded_Set<T>::remove (const T &item) +{ + ACE_TRACE ("ACE_Bounded_Set<T>::remove"); + for (size_t i = 0; i < this->cur_size_; i++) + { + if (this->search_structure_[i].item_ == item) + { + size_t index = i; + + // Mark this entry as being free. + this->search_structure_[i].is_free_ = 1; + + // If we just unbound the highest entry, then we need to + // figure out where the next highest active entry is. + if (i + 1 == this->cur_size_) + { + while (i > 0 && this->search_structure_[--i].is_free_) + continue; + + if (i == 0 && this->search_structure_[i].is_free_) + this->cur_size_ = 0; + else + this->cur_size_ = i + 1; + } + return 1; + } + } + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Set_Iterator) + +template <class T> void +ACE_Bounded_Set_Iterator<T>::dump (void) const +{ + ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::dump"); +} + +template <class T> +ACE_Bounded_Set_Iterator<T>::ACE_Bounded_Set_Iterator (ACE_Bounded_Set<T> &s) + : s_ (s), + next_ (-1) +{ + ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::ACE_Bounded_Set_Iterator"); + this->advance (); +} + +template <class T> int +ACE_Bounded_Set_Iterator<T>::advance (void) +{ + ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::advance"); + for (++this->next_; + size_t (this->next_) < this->s_.cur_size_ + && this->s_.search_structure_[this->next_].is_free_; + ++this->next_) + continue; + + return this->next_; +} + +template <class T> int +ACE_Bounded_Set_Iterator<T>::next (T *&item) +{ + ACE_TRACE ("ACE_Bounded_Set_Iterator<T>::next"); + if (size_t (this->next_) < this->s_.cur_size_) + { + item = &this->s_.search_structure_[this->next_].item_; + return 1; + } + else + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Set_Node) + +template <class T> +class ACE_Set_Node +{ +friend class ACE_Unbounded_Set<T>; +friend class ACE_Unbounded_Set_Iterator<T>; +public: + // = Initialization methods + ACE_Set_Node (const T &i, ACE_Set_Node<T> *n); + ACE_Set_Node (ACE_Set_Node<T> *n = 0); + ACE_Set_Node (const ACE_Set_Node<T> &n); + +private: + ACE_Set_Node<T> *next_; + // Pointer to next element in the list of ACE_Set_Nodes. + + T item_; + // Current value of the item in this node. +}; + +template <class T> +ACE_Set_Node<T>::ACE_Set_Node (const T &i, ACE_Set_Node<T> *n) + : next_ (n), + item_ (i) +{ +// ACE_TRACE ("ACE_Set_Node<T>::ACE_Set_Node"); +} + +template <class T> +ACE_Set_Node<T>::ACE_Set_Node (ACE_Set_Node<T> *n) + : next_ (n) +{ +// ACE_TRACE ("ACE_Set_Node<T>::ACE_Set_Node"); +} + +template <class T> +ACE_Set_Node<T>::ACE_Set_Node (const ACE_Set_Node<T> &s) + : next_ (s.next_), + item_ (s.item_) +{ +// ACE_TRACE ("ACE_Set_Node<T>::ACE_Set_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set) + +template <class T> void +ACE_Unbounded_Set<T>::dump (void) const +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::dump"); +} + +template <class T> +ACE_Unbounded_Set<T>::~ACE_Unbounded_Set (void) +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::~ACE_Unbounded_Set"); + while (this->head_ != 0) + { + ACE_Set_Node<T> *temp = this->head_; + this->head_ = this->head_->next_; + this->cur_size_--; + delete temp; + } +} + +template <class T> int +ACE_Unbounded_Set<T>::find (const T &item) const +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::find"); + for (ACE_Set_Node<T> *temp = this->head_; + temp != 0; + temp = temp->next_) + if (temp->item_ == item) + return 1; + + return 0; +} + +template <class T> +ACE_Unbounded_Set<T>::ACE_Unbounded_Set (void) + : head_ (0), + cur_size_ (0) +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::ACE_Unbounded_Set"); +} + +template <class T> int +ACE_Unbounded_Set<T>::insert (const T &item) +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::insert"); + if (this->find (item) == 0) + { + ACE_NEW_RETURN (this->head_, ACE_Set_Node<T> (item, this->head_), -1); + this->cur_size_++; + return 0; + } + else + return 1; +} + +template <class T> int +ACE_Unbounded_Set<T>::remove (const T &item) +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::remove"); + ACE_Set_Node<T> *prev = 0; + ACE_Set_Node<T> *temp; + + for (temp = this->head_; + temp != 0; + temp = temp->next_) + { + if (temp->item_ == item) + break; + prev = temp; + } + + if (temp == 0) + return 0; + else if (prev == 0) // Deleting the front of the list. + this->head_ = this->head_->next_; + else + prev->next_ = temp->next_; + + this->cur_size_--; + + delete temp; + return 1; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Set_Iterator) + +template <class T> void +ACE_Unbounded_Set_Iterator<T>::dump (void) const +{ +// ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::dump"); +} + +template <class T> +ACE_Unbounded_Set_Iterator<T>::ACE_Unbounded_Set_Iterator (ACE_Unbounded_Set<T> &s) + : current_ (s.head_) +{ +// ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::ACE_Unbounded_Set_Iterator"); +} + +template <class T> int +ACE_Unbounded_Set_Iterator<T>::advance (void) +{ +// ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::advance"); + this->current_ = this->current_->next_; + return 1; +} + +template <class T> int +ACE_Unbounded_Set_Iterator<T>::next (T *&item) +{ +// ACE_TRACE ("ACE_Unbounded_Set_Iterator<T>::next"); + if (this->current_ == 0) + return 0; + else + { + item = &this->current_->item_; + return 1; + } +} + +#endif /* ACE_SET_C */ diff --git a/ace/Set.h b/ace/Set.h new file mode 100644 index 00000000000..be0c3246e56 --- /dev/null +++ b/ace/Set.h @@ -0,0 +1,321 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Set.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SET) +#define ACE_SET + +#include "ace/ACE.h" + +// Forward declarations. +template <class T> class ACE_Unbounded_Set; + +// "Cheshire cat" +template <class T> class ACE_Set_Node; + +template <class T> +class ACE_Unbounded_Set_Iterator + // = TITLE + // Implement an iterator over an unbounded set. +{ +public: + // = Initialization method. + ACE_Unbounded_Set_Iterator (ACE_Unbounded_Set<T> &s); + + // = Iteration methods. + + int next (T *&next_item); + // Pass back the <next_item> that hasn't been seen in the Set. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Set_Node<T> *current_; +}; + +// Forward declaration (use the "Cheshire Cat" approach to information +// hiding). +template <class T> +class ACE_Set_Node; + +template <class T> +class ACE_Unbounded_Set + // = TITLE + // Implement a simple unordered set of <T> of unbounded size. + // + // = DESCRIPTION + // This implementation of an unordered set uses a linked list. + // This implementation does not allow duplicates... +{ +friend class ACE_Unbounded_Set_Iterator<T>; +public: + // = Initialization and termination methods. + ACE_Unbounded_Set (void); + ~ACE_Unbounded_Set (void); + + // = Classic unordered set operations. + int insert (const T &new_item); + // Insert <new_item> into the set (doesn't allow duplicates). + // Returns -1 if failures occur, 1 if item is already present, else + // 0. + + int remove (const T &item); + // Remove first occurrence of <item> from the set. Returns 1 if + // it removes the item, 0 if it can't find the item, and -1 if a + // failure occurs. + + int find (const T &item) const; + // Return first occurrence of <item> from the set. + // Returns 0 if can't find, else 1. + + size_t size (void) const; + // Size of the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Set_Node<T> *head_; + // Head of the linked list of Nodes. + + size_t cur_size_; + // Current size of the set. +}; + +// Forward declaration. +template <class T, size_t SIZE> +class ACE_Fixed_Set; + +template <class T, size_t SIZE> +class ACE_Fixed_Set_Iterator + // = TITLE + // Interates through an unordered set. + // + // = DESCRIPTION + // This implementation of an unordered set uses a fixed array. + // Allows deletions while iteration is occurring. +{ +public: + // = Initialization method. + ACE_Fixed_Set_Iterator (ACE_Fixed_Set<T, SIZE> &s); + + // = Iteration methods. + + int next (T *&next_item); + // Pass back the <next_item> that hasn't been seen in the Set. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Fixed_Set<T, SIZE> &s_; + // Set we are iterating over. + + ssize_t next_; + // How far we've advanced over the set. +}; + +template <class T, size_t SIZE> +class ACE_Fixed_Set + // = TITLE + // Implement a simple unordered set of <T> with maximum <SIZE>. + // + // = DESCRIPTION + // This implementation of an unordered set uses a fixed array. + // This implementation does not allow duplicates... +{ +friend class ACE_Fixed_Set_Iterator<T, SIZE>; +public: + // = Initialization and termination methods. + ACE_Fixed_Set (void); + ~ACE_Fixed_Set (void); + + // = Classic unordered set operations. + int insert (const T &new_item); + // Insert <new_item> into the set (doesn't allow duplicates). + // Returns -1 if failures occur, 1 if item is already present, else + // 0. + + int remove (const T &item); + // Remove first occurrence of <item> from the set. Returns 1 if + // it removes the item, 0 if it can't find the item, and -1 if a + // failure occurs. + + int find (const T &item) const; + // Return first occurrence of <item> from the set. + // Returns 0 if can't find, else 1. + + size_t size (void) const; + // Size of the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + struct + { + T item_; + // Item in the set. + int is_free_; + // Keeps track of whether this item is in use or not. + } search_structure_[SIZE]; + // Holds the contents of the set. + + size_t cur_size_; + // Current size of the set. + + size_t max_size_; + // Maximum size of the set. +}; + +// Forward declaration. +template <class T> +class ACE_Bounded_Set; + +template <class T> +class ACE_Bounded_Set_Iterator + // = TITLE + // Interates through an unordered set. + // + // = DESCRIPTION + // This implementation of an unordered set uses a Bounded array. + // Allows deletions while iteration is occurring. +{ +public: + // = Initialization method. + ACE_Bounded_Set_Iterator (ACE_Bounded_Set<T> &s); + + // = Iteration methods. + + int next (T *&next_item); + // Pass back the <next_item> that hasn't been seen in the Set. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Bounded_Set<T> &s_; + // Set we are iterating over. + + ssize_t next_; + // How far we've advanced over the set. +}; + +template <class T> +class ACE_Bounded_Set + // = TITLE + // Implement a simple unordered set of <T> with maximum + // set at creation time. + // + // = DESCRIPTION + // This implementation of an unordered set uses a Bounded array. + // This implementation does not allow duplicates... +{ +friend class ACE_Bounded_Set_Iterator<T>; +public: + enum + { + DEFAULT_SIZE = 10 + }; + + // = Initialization and termination methods. + ACE_Bounded_Set (void); + ACE_Bounded_Set (size_t size); + ~ACE_Bounded_Set (void); + + // = Classic unordered set operations. + int insert (const T &new_item); + // Insert <new_item> into the set (doesn't allow duplicates). + // Returns -1 if failures occur, 1 if item is already present, else + // 0. + + int remove (const T &item); + // Remove first occurrence of <item> from the set. Returns 1 if it + // removes the item, 0 if it can't find the item, and -1 if a + // failure occurs. + + int find (const T &item) const; + // Return first occurrence of <item> from the set. + // Returns 0 if can't find, else 1. + + size_t size (void) const; + // Size of the set. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + struct Search_Structure + { + T item_; + // Item in the set. + int is_free_; + // Keeps track of whether this item is in use or not. + }; + + Search_Structure *search_structure_; + // Holds the contents of the set. + + size_t cur_size_; + // Current size of the set. + + size_t max_size_; + // Maximum size of the set. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Set.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Set.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Set.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_SET */ diff --git a/ace/Set.i b/ace/Set.i new file mode 100644 index 00000000000..baec2deb9f2 --- /dev/null +++ b/ace/Set.i @@ -0,0 +1,24 @@ +/* -*- C++ -*- */ +// $Id$ + +// Set.i + +template <class T, size_t SIZE> ACE_INLINE size_t +ACE_Fixed_Set<T, SIZE>::size (void) const +{ + return this->cur_size_; +} + +template <class T> ACE_INLINE size_t +ACE_Bounded_Set<T>::size (void) const +{ + ACE_TRACE ("ACE_Bounded_Set<T>::size"); + return this->cur_size_; +} + +template <class T> ACE_INLINE size_t +ACE_Unbounded_Set<T>::size (void) const +{ +// ACE_TRACE ("ACE_Unbounded_Set<T>::size"); + return this->cur_size_; +} diff --git a/ace/Shared_Memory.h b/ace/Shared_Memory.h new file mode 100644 index 00000000000..b175cbde497 --- /dev/null +++ b/ace/Shared_Memory.h @@ -0,0 +1,43 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Shared_Memory.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SHARED_MEMORY_H) +#define ACE_SHARED_MEMORY_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Shared_Memory + // = TITLE + // This base class adapts both System V shared memory and "BSD" + // mmap to a common API. + // + // = DESCRIPTION + // This is a very simple-minded wrapper, i.e., it really is only + // useful for allocating large contiguous chunks of shared + // memory. For a much more sophisticated version, please check + // out the <ACE_Malloc> class. +{ +public: + // = Note that all methods are pure virtual. + virtual int close (void) = 0; + virtual int remove (void) = 0; + virtual void *malloc (size_t = 0) = 0; + virtual int free (void *p) = 0; + virtual int get_segment_size (void) const = 0; + virtual ACE_HANDLE get_id (void) const = 0; +}; +#endif /* ACE_SHARED_MEMORY_H */ diff --git a/ace/Shared_Memory_MM.cpp b/ace/Shared_Memory_MM.cpp new file mode 100644 index 00000000000..cc5f93846c4 --- /dev/null +++ b/ace/Shared_Memory_MM.cpp @@ -0,0 +1,52 @@ +// Shared_Memory_MM.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Shared_Memory_MM.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Shared_Memory_MM.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_MM) + +void +ACE_Shared_Memory_MM::dump (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_MM::dump"); +} + +// Creates a shared memory segment of SIZE bytes. + +ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (ACE_HANDLE handle, + int length, + int prot, + int share, + char *addr, + off_t pos) + : shared_memory_ (handle, length, prot, share, addr, pos) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::ACE_Shared_Memory_MM"); +} + +ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (char file_name[], + int len, + int flags, + int mode, + int prot, + int share, + char *addr, + off_t pos) + : shared_memory_ (file_name, len, flags, mode, + prot, share, addr, pos) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::ACE_Shared_Memory_MM"); +} + +// The "do-nothing" constructor. + +ACE_Shared_Memory_MM::ACE_Shared_Memory_MM (void) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::ACE_Shared_Memory_MM"); +} + diff --git a/ace/Shared_Memory_MM.h b/ace/Shared_Memory_MM.h new file mode 100644 index 00000000000..9567e0e33df --- /dev/null +++ b/ace/Shared_Memory_MM.h @@ -0,0 +1,95 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Shared_Memory_MM.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SHARED_MALLOC_MM_H) +#define ACE_SHARED_MALLOC_MM_H + +#include "ace/Shared_Memory.h" +#include "ace/Mem_Map.h" + +class ACE_Export ACE_Shared_Memory_MM : public ACE_Shared_Memory + // = TITLE + // Shared memory wrapper based on MMAP. +{ +public: + // = Initialization and termination methods. + ACE_Shared_Memory_MM (void); + ACE_Shared_Memory_MM (ACE_HANDLE handle, + int length = -1, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + char *addr = 0, + off_t pos = 0); + ACE_Shared_Memory_MM (char file_name[], + int len = -1, + int flags = O_RDWR | O_CREAT, + int mode = ACE_DEFAULT_PERMS, + int prot = PROT_RDWR, + int share = MAP_SHARED, + char *addr = 0, off_t pos = 0); + + int open (ACE_HANDLE handle, + int length = -1, + int prot = PROT_RDWR, + int share = MAP_PRIVATE, + char *addr = 0, + off_t pos = 0); + + int open (char file_name[], + int len = -1, + int flags = O_RDWR | O_CREAT, + int mode = ACE_DEFAULT_PERMS, + int prot = PROT_RDWR, + int share = MAP_SHARED, + char *addr = 0, + off_t pos = 0); + + virtual int close (void); + // Close down the shared memory segment. + + virtual int remove (void); + // Remove the shared memory segment and the underlying file. + + // = Allocation and deallocation methods. + virtual void *malloc (size_t size = 0); + // Create a new chuck of memory containing <size> bytes. + + virtual int free (void *p); + // Free a chuck of memory allocated by <ACE_Shared_Memory_MM::malloc>. + + virtual int get_segment_size (void) const; + // Return the size of the shared memory segment. + + virtual ACE_HANDLE get_id (void) const; + // Return the ID of the shared memory segment (i.e., an ACE_HANDLE). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Mem_Map shared_memory_; + // This version is implemented with memory-mapped files. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Shared_Memory_MM.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SHARED_MALLOC_MM_H */ diff --git a/ace/Shared_Memory_MM.i b/ace/Shared_Memory_MM.i new file mode 100644 index 00000000000..4f49965c3f3 --- /dev/null +++ b/ace/Shared_Memory_MM.i @@ -0,0 +1,81 @@ +/* -*- C++ -*- */ +// $Id$ + +// Shared_Memory_MM.i + +ACE_INLINE int +ACE_Shared_Memory_MM::open (ACE_HANDLE handle, + int length, + int prot, + int share, + char *addr, + off_t pos) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::open"); + return shared_memory_.map (handle, length, prot, share, addr, pos); +} + +ACE_INLINE int +ACE_Shared_Memory_MM::open (char file_name[], + int len, + int flags, + int mode, + int prot, + int share, + char *addr, + off_t pos) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::open"); + return shared_memory_.map (file_name, len, flags, mode, + prot, share, addr, pos); +} + +// The overall size of the segment. + +ACE_INLINE int +ACE_Shared_Memory_MM::get_segment_size (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_MM::get_segment_size"); + return this->shared_memory_.size (); +} + +// Unmaps the shared memory segment. + +ACE_INLINE int +ACE_Shared_Memory_MM::remove (void) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::remove"); + return shared_memory_.unmap (); +} + +// Closes (unmaps) the shared memory segment. + +ACE_INLINE int +ACE_Shared_Memory_MM::close (void) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::close"); + return shared_memory_.unmap (); +} + +ACE_INLINE void * +ACE_Shared_Memory_MM::malloc (size_t) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::malloc"); + void *addr; + + return this->shared_memory_ (addr) == -1 ? 0 : addr; +} + +ACE_INLINE ACE_HANDLE +ACE_Shared_Memory_MM::get_id (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_MM::get_id"); + return this->shared_memory_.handle (); +} + +ACE_INLINE int +ACE_Shared_Memory_MM::free (void *p) +{ + ACE_TRACE ("ACE_Shared_Memory_MM::free"); + return p != 0; +} diff --git a/ace/Shared_Memory_SV.cpp b/ace/Shared_Memory_SV.cpp new file mode 100644 index 00000000000..eec600c2ea1 --- /dev/null +++ b/ace/Shared_Memory_SV.cpp @@ -0,0 +1,29 @@ +// Shared_Memory_SV.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Shared_Memory_SV.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Shared_Memory_SV.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Shared_Memory_SV) + +void +ACE_Shared_Memory_SV::dump (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_SV::dump"); +} + +ACE_Shared_Memory_SV::ACE_Shared_Memory_SV (key_t id, + int length, + int create, + int perms, + void *addr, + int flags) + : shared_memory_ (id, length, create, perms, addr, flags) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::ACE_Shared_Memory_SV"); +} + diff --git a/ace/Shared_Memory_SV.h b/ace/Shared_Memory_SV.h new file mode 100644 index 00000000000..56ee316cd38 --- /dev/null +++ b/ace/Shared_Memory_SV.h @@ -0,0 +1,87 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Shared_Memory_SV.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SHARED_MALLOC_SV_H) +#define ACE_SHARED_MALLOC_SV_H + +#include "ace/Shared_Memory.h" +#include "ace/SV_Shared_Memory.h" + +class ACE_Export ACE_Shared_Memory_SV : public ACE_Shared_Memory + // = TITLE + // Shared memory wrapper based on System V shared memory. +{ +public: + enum + { + ACE_CREATE = IPC_CREAT, + ACE_OPEN = 0 + }; + + // = Initialization and termination methods. + ACE_Shared_Memory_SV (void); + ACE_Shared_Memory_SV (key_t id, + int length, + int create = ACE_Shared_Memory_SV::ACE_OPEN, + int perms = ACE_DEFAULT_PERMS, + void *addr = 0, + int flags = 0); + + int open (key_t id, + int length, + int create = ACE_Shared_Memory_SV::ACE_OPEN, + int perms = ACE_DEFAULT_PERMS, + void *addr = 0, + int flags = 0); + + virtual int close (void); + // Close down the shared memory segment. + + virtual int remove (void); + // Remove the shared memory segment and the underlying file. + + // = Allocation and deallocation methods. + virtual void *malloc (size_t = 0); + // Create a new chuck of memory containing <size> bytes. + + virtual int free (void *p); + // Free a chuck of memory allocated by <ACE_Shared_Memory_SV::malloc>. + + virtual int get_segment_size (void) const; + // Return the size of the shared memory segment. + + virtual ACE_HANDLE get_id (void) const; + // Return the ID of the shared memory segment (i.e., a System V + // shared memory internal id). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_SV_Shared_Memory shared_memory_; + // This version is implemented with System V shared memory + // segments. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Shared_Memory_SV.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SHARED_MALLOC_SV_H */ diff --git a/ace/Shared_Memory_SV.i b/ace/Shared_Memory_SV.i new file mode 100644 index 00000000000..400d9e63201 --- /dev/null +++ b/ace/Shared_Memory_SV.i @@ -0,0 +1,73 @@ +/* -*- C++ -*- */ +// $Id$ + +// Shared_Memory_SV.i + +ACE_INLINE int +ACE_Shared_Memory_SV::open (key_t id, + int length, + int create, + int perms, + void *addr, + int flags) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::open"); + return shared_memory_.open_and_attach (id, length, create, + perms, addr, flags); +} + +// The overall size of the segment. + +ACE_INLINE int +ACE_Shared_Memory_SV::get_segment_size (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_SV::get_segment_size"); + return this->shared_memory_.get_segment_size (); +} + +// Removes the shared memory segment. + +ACE_INLINE int +ACE_Shared_Memory_SV::remove (void) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::remove"); + return shared_memory_.remove (); +} + +// Closes (detaches) the shared memory segment. + +ACE_INLINE int +ACE_Shared_Memory_SV::close (void) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::close"); + return shared_memory_.detach (); +} + +ACE_INLINE void * +ACE_Shared_Memory_SV::malloc (size_t) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::malloc"); + return this->shared_memory_.get_segment_ptr (); +} + +ACE_INLINE ACE_HANDLE +ACE_Shared_Memory_SV::get_id (void) const +{ + ACE_TRACE ("ACE_Shared_Memory_SV::get_id"); + return this->shared_memory_.get_id (); +} + +// The "do-nothing" constructor. + +ACE_INLINE +ACE_Shared_Memory_SV::ACE_Shared_Memory_SV (void) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::ACE_Shared_Memory_SV"); +} + +ACE_INLINE int +ACE_Shared_Memory_SV::free (void *p) +{ + ACE_TRACE ("ACE_Shared_Memory_SV::free"); + return p != 0; +} diff --git a/ace/Shared_Object.cpp b/ace/Shared_Object.cpp new file mode 100644 index 00000000000..a18c728959e --- /dev/null +++ b/ace/Shared_Object.cpp @@ -0,0 +1,46 @@ +// Shared_Object.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Shared_Object.h" +/* Provide the abstract base class used to access dynamic linking + facilities */ + + +#if !defined (__ACE_INLINE__) +#include "ace/Shared_Object.i" +#endif /* __ACE_INLINE__ */ + +// Initializes object when dynamic linking occurs. + +int +ACE_Shared_Object::init (int, char *[]) +{ + ACE_TRACE ("ACE_Shared_Object::init"); + return -1; +} + +// Terminates object when dynamic unlinking occurs. + +int +ACE_Shared_Object::fini (void) +{ + ACE_TRACE ("ACE_Shared_Object::fini"); + return -1; +} + +// Returns information on active object. + +int +ACE_Shared_Object::info (char **, size_t) const +{ + ACE_TRACE ("ACE_Shared_Object::info"); + return -1; +} + +// Need to give a default implementation. + +ACE_Shared_Object::~ACE_Shared_Object (void) +{ + ACE_TRACE ("ACE_Shared_Object::~ACE_Shared_Object"); +} diff --git a/ace/Shared_Object.h b/ace/Shared_Object.h new file mode 100644 index 00000000000..7298a53b9a6 --- /dev/null +++ b/ace/Shared_Object.h @@ -0,0 +1,45 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Shared_Object.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SHARED_OBJECT_H) +#define ACE_SHARED_OBJECT_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Shared_Object + // = TITLE + // Provide the abstract base class used to access dynamic linking + // facilities +{ +public: + virtual int init (int argc, char *argv[]); + // Initializes object when dynamic linking occurs. + + virtual int fini (void); + // Terminates object when dynamic unlinking occurs. + + virtual int info (char **info_string, size_t length = 0) const; + // Returns information on active object. + + virtual ~ACE_Shared_Object (void); +}; + +#if defined (__ACE_INLINE__) +#include "ace/Shared_Object.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SHARED_OBJECT_H */ diff --git a/ace/Shared_Object.i b/ace/Shared_Object.i new file mode 100644 index 00000000000..c6840a221cc --- /dev/null +++ b/ace/Shared_Object.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Shared_Object.i diff --git a/ace/Signal.cpp b/ace/Signal.cpp new file mode 100644 index 00000000000..5acd5195d66 --- /dev/null +++ b/ace/Signal.cpp @@ -0,0 +1,632 @@ +// Signal.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Signal.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Signal.i" +#endif /* __ACE_INLINE__ */ + +// Static definitions. + +#if defined (ACE_MT_SAFE) +ACE_Recursive_Thread_Mutex ACE_Sig_Handler::ace_sig_handler_lock_; +#endif /* ACE_MT_SAFE */ + +// Array of Event_Handlers that will handle the signals. +ACE_Event_Handler *ACE_Sig_Handler::signal_handlers_[NSIG]; + +// Remembers if a signal has occurred. +sig_atomic_t ACE_Sig_Handler::sig_pending_ = 0; + +ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Action) + +void +ACE_Sig_Action::dump (void) const +{ + ACE_TRACE ("ACE_Sig_Action::dump"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Set) + +void +ACE_Sig_Set::dump (void) const +{ + ACE_TRACE ("ACE_Sig_Set::dump"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Guard) + +void +ACE_Sig_Guard::dump (void) const +{ + ACE_TRACE ("ACE_Sig_Guard::dump"); +} + +ACE_Sig_Action::ACE_Sig_Action (void) +{ + ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action"); + this->sa_.sa_flags = 0; + ACE_OS::sigemptyset (&this->sa_.sa_mask); + this->sa_.sa_handler = 0; +} + +ACE_Sig_Action::ACE_Sig_Action (ACE_SignalHandler sig_handler, + sigset_t *sig_mask, + int sig_flags) +{ + ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action"); + this->sa_.sa_flags = sig_flags; + + if (sig_mask == 0) + ACE_OS::sigemptyset (&this->sa_.sa_mask); + else + this->sa_.sa_mask = *sig_mask; // Structure assignment... + + this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler); +} + +ACE_Sig_Action::ACE_Sig_Action (ACE_SignalHandler sig_handler, + int signum, + sigset_t *sig_mask, + int sig_flags) +{ + ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action"); + this->sa_.sa_flags = sig_flags; + + if (sig_mask == 0) + ACE_OS::sigemptyset (&this->sa_.sa_mask); + else + this->sa_.sa_mask = *sig_mask; // Structure assignment... + + this->sa_.sa_handler = ACE_SignalHandlerV (sig_handler); + ACE_OS::sigaction (signum, &this->sa_, 0); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handler) + +void +ACE_Sig_Handler::dump (void) const +{ + ACE_TRACE ("ACE_Sig_Handler::dump"); +} + +sig_atomic_t +ACE_Sig_Handler::sig_pending (void) +{ + ACE_TRACE ("ACE_Sig_Handler::sig_pending"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + return ACE_Sig_Handler::sig_pending_; +} + +void +ACE_Sig_Handler::sig_pending (sig_atomic_t pending) +{ + ACE_TRACE ("ACE_Sig_Handler::sig_pending"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + ACE_Sig_Handler::sig_pending_ = pending; +} + +ACE_Event_Handler * +ACE_Sig_Handler::handler (int signum) +{ + ACE_TRACE ("ACE_Sig_Handler::handler"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + if (ACE_Sig_Handler::in_range (signum)) + return ACE_Sig_Handler::signal_handlers_[signum]; + else + return 0; +} + +ACE_Event_Handler * +ACE_Sig_Handler::handler (int signum, ACE_Event_Handler *new_sh) +{ + ACE_TRACE ("ACE_Sig_Handler::handler"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + if (ACE_Sig_Handler::in_range (signum)) + { + ACE_Event_Handler *sh = ACE_Sig_Handler::signal_handlers_[signum]; + + ACE_Sig_Handler::signal_handlers_[signum] = new_sh; + return sh; + } + else + return 0; +} + +// Register an ACE_Event_Handler along with the corresponding SIGNUM. + +int +ACE_Sig_Handler::register_handler (int signum, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp, + ACE_Event_Handler **old_sh, + ACE_Sig_Action *old_disp) +{ + ACE_TRACE ("ACE_Sig_Handler::register_handler"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + if (ACE_Sig_Handler::in_range (signum)) + { + ACE_Sig_Action sa; // Define a "null" action. + ACE_Event_Handler *sh = this->handler (signum, new_sh); + + // Stack the old ACE_Sig_Handler if the user gives us a pointer + // to a object. + if (old_sh != 0) + *old_sh = sh; + + // Make sure that new_disp points to a valid location if the + // user doesn't care... + if (new_disp == 0) + new_disp = &sa; + + new_disp->handler (ACE_SignalHandler (ACE_Sig_Handler::dispatch)); + new_disp->flags (new_disp->flags () | SA_SIGINFO); + return new_disp->register_action (signum, old_disp); + } + else + return -1; +} + +// Remove an ACE_Event_Handler. + +int +ACE_Sig_Handler::remove_handler (int signum, + ACE_Sig_Action *new_disp, + ACE_Sig_Action *old_disp, + int sigkey) +{ + ACE_TRACE ("ACE_Sig_Handler::remove_handler"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + if (ACE_Sig_Handler::in_range (signum)) + { + ACE_Sig_Action sa (SIG_DFL); // Define the default disposition. + + if (new_disp == 0) + new_disp = &sa; + + ACE_Sig_Handler::signal_handlers_[signum] = 0; + + // Register either the new disposition or restore the default. + return new_disp->register_action (signum, old_disp); + } + else + return -1; +} + +// Master dispatcher function that gets called by a signal handler and +// dispatches one handler... + +void +ACE_Sig_Handler::dispatch (int signum, + siginfo_t *siginfo, + ucontext_t *ucontext) +{ + ACE_TRACE ("ACE_Sig_Handler::dispatch"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + // Preserve errno across callbacks! + int old_errno = errno; + + ACE_Sig_Handler::sig_pending (1); + + // Darn well better be in range since the OS dispatched this... + ACE_ASSERT (ACE_Sig_Handler::in_range (signum)); + + ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum]; + + if (eh != 0 && eh->handle_signal (signum, siginfo, ucontext) == -1) + { + // Define the default disposition. + ACE_Sig_Action sa (SIG_DFL); + + ACE_Sig_Handler::signal_handlers_[signum] = 0; + + // Remove the current disposition by registering the default + // disposition. + sa.register_action (signum); + } + + // Restore error when callback completes. + errno = old_errno; +} + +ACE_Sig_Adapter::ACE_Sig_Adapter (ACE_Sig_Action &sa, int sigkey) + : sa_ (sa), + type_ (SIG_ACTION), + sigkey_ (sigkey) +{ + ACE_TRACE ("ACE_Sig_Adapter::ACE_Sig_Adapter"); +} + +ACE_Sig_Adapter::ACE_Sig_Adapter (ACE_Event_Handler *eh, + int sigkey) + : eh_ (eh), + type_ (ACE_HANDLER), + sigkey_ (sigkey) +{ + ACE_TRACE ("ACE_Sig_Adapter::ACE_Sig_Adapter"); +} + +ACE_Sig_Adapter::ACE_Sig_Adapter (ACE_Sig_Handler_Ex sig_func, + int sigkey) + : sig_func_ (sig_func), + type_ (C_FUNCTION), + sigkey_ (sigkey) +{ + ACE_TRACE ("ACE_Sig_Adapter::ACE_Sig_Adapter"); +} + +int +ACE_Sig_Adapter::sigkey (void) +{ + ACE_TRACE ("ACE_Sig_Adapter::sigkey"); + return this->sigkey_; +} + +int +ACE_Sig_Adapter::handle_signal (int signum, + siginfo_t *siginfo, + ucontext_t *ucontext) +{ + ACE_TRACE ("ACE_Sig_Adapter::handle_signal"); + + switch (this->type_) + { + case SIG_ACTION: + { + // We have to dispatch a handler that was registered by a + // third-party library. + + ACE_Sig_Action old_disp; + + // Make sure this handler executes in the context it was + // expecting... + this->sa_.register_action (signum, &old_disp); + + ACE_Sig_Handler_Ex sig_func = ACE_Sig_Handler_Ex (this->sa_.handler ()); + + (*sig_func) (signum, siginfo, ucontext); + // Restore the original disposition. + old_disp.register_action (signum); + break; + } + case ACE_HANDLER: + this->eh_->handle_signal (signum, siginfo, ucontext); + break; + case C_FUNCTION: + (*this->sig_func_) (signum, siginfo, ucontext); + break; + } + return 0; +} + +// ---------------------------------------- +// The following classes are local to this file. + +// HPUX sucks big time! +#if !defined (HPUX) +// This needs to be fixed... +#define ACE_MAX_SIGNAL_HANDLERS size_t (20) + +// Keeps track of the id that uniquely identifies each registered +// signal handler. This id can be used to cancel a timer via the +// <remove_handler> method. +int ACE_Sig_Handlers::sigkey_ = 0; + +// If this is > 0 then a 3rd party library has registered a +// handler... +int ACE_Sig_Handlers::third_party_sig_handler_ = 0; + +// Make life easier by defining typedefs... +typedef ACE_Fixed_Set <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> + ACE_SIG_HANDLERS_SET; +typedef ACE_Fixed_Set_Iterator <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> + ACE_SIG_HANDLERS_ITERATOR; + +class ACE_Sig_Handlers_Set +{ +public: + static ACE_SIG_HANDLERS_SET *instance (int signum); + +private: + static ACE_SIG_HANDLERS_SET *sig_handlers_[NSIG]; +}; + +/* static */ +ACE_SIG_HANDLERS_SET *ACE_Sig_Handlers_Set::sig_handlers_[NSIG]; + +/* static */ +ACE_SIG_HANDLERS_SET * +ACE_Sig_Handlers_Set::instance (int signum) +{ + if (signum <= 0 || signum >= NSIG) + return 0; // This will cause problems... + else if (ACE_Sig_Handlers_Set::sig_handlers_[signum] == 0) + ACE_NEW_RETURN (ACE_Sig_Handlers_Set::sig_handlers_[signum], ACE_SIG_HANDLERS_SET, 0); + + return ACE_Sig_Handlers_Set::sig_handlers_[signum]; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handlers) + +void +ACE_Sig_Handlers::dump (void) const +{ + ACE_TRACE ("ACE_Sig_Handlers::dump"); +} + +// This is the method that does all the dirty work... The basic +// structure of this method was devised by Detlef Becker +// (beckerd@erlh.siemens.de). + +int +ACE_Sig_Handlers::register_handler (int signum, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp, + ACE_Event_Handler **old_sh, + ACE_Sig_Action *old_disp) +{ + ACE_TRACE ("ACE_Sig_Handlers::register_handler"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + if (ACE_Sig_Handler::in_range (signum)) + { + ACE_Sig_Adapter *ace_sig_adapter = 0; // Our signal handler. + ACE_Sig_Adapter *extern_sh = 0; // An external signal handler. + ACE_Sig_Action sa; + + // Get current signal disposition. + sa.retrieve_action (signum); + + // Check whether we are already in control of the signal + // handling disposition... + + if (!(sa.handler () == ACE_SignalHandler (ACE_Sig_Handlers::dispatch) + || sa.handler () == ACE_SignalHandler (SIG_IGN) + || sa.handler () == ACE_SignalHandler (SIG_DFL))) + { + // Drat, a 3rd party library has already installed a signal ;-( + + // Upto here we never disabled RESTART_MODE. Thus, + // RESTART_MODE can only be changed by 3rd party libraries. + + if (ACE_BIT_DISABLED (sa.flags (), SA_RESTART) + && ACE_Sig_Handlers::third_party_sig_handler_) + // Toggling is disallowed since we might break 3rd party + // code. + return -1; + + // Note that we've seen a 3rd party handler... + ACE_Sig_Handlers::third_party_sig_handler_ = 1; + + // Create a new 3rd party disposition, remembering its + // preferred signal blocking etc...; + ACE_NEW_RETURN (extern_sh, ACE_Sig_Adapter (sa, ++ACE_Sig_Handlers::sigkey_), -1); + + // Add the external signal handler to the set of handlers + // for this signal. + if (ACE_Sig_Handlers_Set::instance (signum)->insert (extern_sh) == -1) + { + delete extern_sh; + return -1; + } + } + // Add our new handler at this point. + ACE_NEW_RETURN (ace_sig_adapter, ACE_Sig_Adapter (new_sh, ++ACE_Sig_Handlers::sigkey_), -1); + + // Add the ACE signal handler to the set of handlers for this + // signal (make sure it goes before the external one if there is + // one of these). + if (ACE_Sig_Handlers_Set::instance (signum)->insert (ace_sig_adapter) == -1) + { + // We couldn't reinstall our handler, so let's pretend like + // none of this happened... + if (extern_sh) + { + ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh); + delete extern_sh; + } + delete ace_sig_adapter; + return -1; + } + // If ACE_Sig_Handler::dispatch() was set we're done. + else if (sa.handler () == ACE_SignalHandler (ACE_Sig_Handlers::dispatch)) + return ace_sig_adapter->sigkey (); + + // Otherwise, we need to register our handler function so that + // all signals will be dispatched through ACE. + else + { + // Make sure that new_disp points to a valid location if the + // user doesn't care... + if (new_disp == 0) + new_disp = &sa; + + new_disp->handler (ACE_SignalHandler (ACE_Sig_Handlers::dispatch)); + + // Default is to restart signal handlers. + new_disp->flags (new_disp->flags () | SA_RESTART); + new_disp->flags (new_disp->flags () | SA_SIGINFO); + + // Finally install (possibly reinstall) the ACE signal + // handler disposition with the SA_RESTART mode enabled. + if (new_disp->register_action (signum, old_disp) == -1) + { + // Yikes, lots of roll back at this point... + ACE_Sig_Handlers_Set::instance (signum)->remove (ace_sig_adapter); + delete ace_sig_adapter; + + if (extern_sh) + { + ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh); + delete extern_sh; + } + return -1; + } + else // Return the signal key so that programs can cancel this + // handler if they want! + return ace_sig_adapter->sigkey (); + } + } + else + return -1; +} + +// Remove the ACE_Event_Handler currently associated with <signum>. +// Install the new disposition (if given) and return the previous +// disposition (if desired by the caller). Returns 0 on success and +// -1 if <signum> is invalid. + +int +ACE_Sig_Handlers::remove_handler (int signum, + ACE_Sig_Action *new_disp, + ACE_Sig_Action *old_disp, + int sigkey) +{ + ACE_TRACE ("ACE_Sig_Handlers::remove_handler"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + if (ACE_Sig_Handler::in_range (signum)) + { + ACE_SIG_HANDLERS_SET *handler_set = + ACE_Sig_Handlers_Set::instance (signum); + + ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set); + + // Iterate through the set of handlers for this signal. + + for (ACE_Event_Handler **eh; + handler_iterator.next (eh) != 0; + handler_iterator.advance ()) + { + // Type-safe downcast would be nice here... + ACE_Sig_Adapter *sh = (ACE_Sig_Adapter *) *eh; + + // Remove the handler if (1) it's key matches the key we've + // been told to remove or (2) if we've been told to remove + // *all* handlers (i.e., <sigkey> == -1). + + if (sh->sigkey () == sigkey || sigkey == -1) + { + handler_set->remove (*eh); + delete *eh; + } + } + + if (handler_set->size () == 0) + { + // If there are no more handlers left for a signal then + // register the new disposition or restore the default + // disposition. + + ACE_Sig_Action sa (SIG_DFL); + + if (new_disp == 0) + new_disp = &sa; + + return new_disp->register_action (signum, old_disp); + } + return 0; + } + else + return -1; +} + +// Master dispatcher function that gets called by a signal handler and +// dispatches *all* the handlers... + +void +ACE_Sig_Handlers::dispatch (int signum, + siginfo_t *siginfo, + ucontext_t *ucontext) +{ + ACE_TRACE ("ACE_Sig_Handlers::dispatch"); + ACE_MT (ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (ACE_Sig_Handler::ace_sig_handler_lock_)); + + // Preserve errno across callbacks! + int old_errno = errno; + + ACE_Sig_Handler::sig_pending (1); + + // Darn well better be in range since the OS dispatched this... + ACE_ASSERT (ACE_Sig_Handler::in_range (signum)); + + ACE_SIG_HANDLERS_SET *handler_set = + ACE_Sig_Handlers_Set::instance (signum); + + ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set); + + for (ACE_Event_Handler **eh = 0; + handler_iterator.next (eh) != 0; + handler_iterator.advance ()) + { + if ((*eh)->handle_signal (signum, siginfo, ucontext) == -1) + { + handler_set->remove (*eh); + delete *eh; + } + } + + // Restore error when callback completes. + errno = old_errno; +} + +// Return the first item in the list of handlers. Note that this will +// trivially provide the same behavior as the ACE_Sig_Handler +// version if there is only 1 handler registered! + +ACE_Event_Handler * +ACE_Sig_Handlers::handler (int signum) +{ + ACE_TRACE ("ACE_Sig_Handlers::handler"); + ACE_SIG_HANDLERS_SET *handler_set = + ACE_Sig_Handlers_Set::instance (signum); + ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set); + ACE_Event_Handler **eh = 0; + handler_iterator.next (eh); + return *eh; +} + +// The following is a strange bit of logic that tries to give the same +// semantics as what happens in ACE_Sig_Handler when we replace the +// current signal handler with a new one. Note that if there is only +// one signal handler the behavior will be identical. If there is +// more than one handler then things get weird... + +ACE_Event_Handler * +ACE_Sig_Handlers::handler (int signum, ACE_Event_Handler *new_sh) +{ + ACE_TRACE ("ACE_Sig_Handlers::handler"); + ACE_SIG_HANDLERS_SET *handler_set = + ACE_Sig_Handlers_Set::instance (signum); + ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set); + ACE_Event_Handler **eh = 0; + + // Find the first handler... + handler_iterator.next (eh); + + // ... then remove it from the set ... + handler_set->remove (*eh); + + // ... and then insert the new signal handler into the beginning of + // the set (note, this is a bit too tied up in the implementation of + // ACE_Unbounded_Set...). + ACE_Sig_Adapter *temp; + + ACE_NEW_RETURN (temp, ACE_Sig_Adapter (new_sh, ++ACE_Sig_Handlers::sigkey_), 0); + handler_set->insert (temp); + return *eh; +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Fixed_Set<ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS>; +template class ACE_Fixed_Set_Iterator<ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ +#endif /* HPUX */ diff --git a/ace/Signal.h b/ace/Signal.h new file mode 100644 index 00000000000..9396ac8c807 --- /dev/null +++ b/ace/Signal.h @@ -0,0 +1,350 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Signal.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SIGNAL_HANDLER_H) +#define ACE_SIGNAL_HANDLER_H + +#include "ace/Synch.h" +#include "ace/Event_Handler.h" +#include "ace/Set.h" + +// This worksaround a horrible bug with HP/UX C++... +typedef struct sigaction ACE_SIGACTION; + +class ACE_Export ACE_Sig_Set + // = TITLE + // Provide a C++ wrapper for the C sigset_t interface. + // + // = DESCRIPTION + // Handle signals via a more elegant C++ interface (e.g., + // doesn't require the use of global variables or global + // functions in an application). +{ +public: + // = Initialization and termination methods. + ACE_Sig_Set (sigset_t *); + ACE_Sig_Set (int fill = 0); + ~ACE_Sig_Set (void); + + int empty_set (void); + // Create a set that excludes all signals defined by the system. + + int fill_set (void); + // Create a set that includes all signals defined by the system. + + int sig_add (int signo); + // Adds the individual signal specified by <signo> to the set. + + int sig_del (int signo); + // Deletes the individual signal specified by <signo> from the set. + + int is_member (int signo) const; + // Checks whether the signal specified by <signo> is in the set. + + operator sigset_t *(); + // Returns a pointer to the underlying sigset_t. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + sigset_t sigset_; + // Set of signals. +}; + +class ACE_Export ACE_Sig_Action + // = TITLE + // C++ wrapper around struct sigaction. +{ +public: + // = Initialization methods. + ACE_Sig_Action (void); + ACE_Sig_Action (ACE_SignalHandler handler, + sigset_t *sigmask = 0, + int flags = 0); + ACE_Sig_Action (ACE_SignalHandler handler, + int signum, + sigset_t *sigmask = 0, + int flags = 0); + ACE_Sig_Action (const ACE_Sig_Action &s); + ACE_Sig_Action (struct sigaction *); + + // = Signal action management. + int register_action (int signum, ACE_Sig_Action *oaction = 0); + // Register <this> as the current disposition and store old + // disposition into <oaction> if it is non-NULL. + + int restore_action (int signum, ACE_Sig_Action &oaction); + // Assign the value of <oaction> to <this> and make it become the + // new signal disposition. + + int retrieve_action (int signum); + // Retrieve the current disposition into <this>. + + // = Set/get current signal action. + void set (struct sigaction *); + struct sigaction *get (void); + operator ACE_SIGACTION *(); + + // = Set/get current signal flags. + void flags (int); + int flags (void); + + // = Set/get current signal mask. + void mask (sigset_t *); + sigset_t *mask (void); + + // = Set/get current signal handler (pointer to function). + void handler (ACE_SignalHandler); + ACE_SignalHandler handler (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + struct sigaction sa_; + // Controls signal behavior. +}; + +class ACE_Export ACE_Sig_Guard + // = TITLE + // Hold signals in MASK for duration of a C++ statement block. + // Note that a "0" for mask causes all signals to be held. +{ +public: + // = Set/remove mask. + ACE_Sig_Guard (ACE_Sig_Set *mask = 0); + ~ACE_Sig_Guard (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Sig_Set omask_; + // Original signal mask. +}; + +class ACE_Export ACE_Sig_Handler + // = TITLE + // This is the main dispatcher of signals for ACE. It improves + // the existing UNIX signal handling mechanism by allowing C++ + // objects to handle signals in a way that avoids the use of + // global/static variables and functions. + // + // = DESCRIPTION + // Using this class a program can register an <ACE_Event_Handler> + // with the <ACE_Sig_Handler> in order to handle a designated + // <signum>. When a signal occurs that corresponds to this + // <signum>, the <handle_signal> method of the registered + // <ACE_Event_Handler> is invoked automatically. +{ +public: + // = Registration and removal methods. + virtual int register_handler (int signum, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp = 0, + ACE_Event_Handler **old_sh = 0, + ACE_Sig_Action *old_disp = 0); + // Add a new <ACE_Event_Handler> and a new sigaction associated with + // <signum>. Passes back the existing ACE_Event_Handler and its + // sigaction if pointers are non-zero. Returns -1 on failure and >= + // 0 on success. + + virtual int remove_handler (int signum, + ACE_Sig_Action *new_disp = 0, + ACE_Sig_Action *old_disp = 0, + int sigkey = -1); + // Remove the <ACE_Event_Handler> currently associated with + // <signum>. <sigkey> is ignored in this implementation since there + // is only one instance of a signal handler. Install the new + // disposition (if given) and return the previous disposition (if + // desired by the caller). Returns 0 on success and -1 if <signum> + // is invalid. + + // Set/get signal status. + static sig_atomic_t sig_pending (void); + // True if there is a pending signal. + + static void sig_pending (sig_atomic_t); + // Reset the value of <sig_pending_> so that no signal is pending. + + // = Set/get the handler associated with a particular signal. + + virtual ACE_Event_Handler *handler (int signum); + // Return the list of <ACE_Sig_Handlers> associated with <signum>. + + virtual ACE_Event_Handler *handler (int signum, ACE_Event_Handler *); + // Set a new <ACE_Event_Handler> that is associated with <signum>. + // Return the existing handler. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = These methods and data members are shared by derived classes. + + static int in_range (int signum); + // Check whether the SIGNUM is within the legal range of signals. + + static sig_atomic_t sig_pending_; + // Keeps track of whether a signal is pending. + +#if defined (ACE_MT_SAFE) + static ACE_Recursive_Thread_Mutex ace_sig_handler_lock_; +#endif /* ACE_MT_SAFE */ + +private: + static void dispatch (int, siginfo_t *, ucontext_t *); + // Callback routine registered with sigaction(2) that dispatches the + // handle_signal() method of the appropriate pre-registered + // ACE_Event_Handler. + + static ACE_Event_Handler *signal_handlers_[NSIG]; + // Array used to store one user-defined Event_Handler for every + // signal. +}; + +class ACE_Export ACE_Sig_Adapter : public ACE_Event_Handler + // = TITLE + // Provide an adapter that transforms various types of signal + // handlers into the scheme used by the <ACE_Reactor>. + +{ +public: + ACE_Sig_Adapter (ACE_Sig_Action &, int sigkey); + ACE_Sig_Adapter (ACE_Event_Handler *, int sigkey); + ACE_Sig_Adapter (ACE_Sig_Handler_Ex, int sigkey = 0); + + int sigkey (void); + // Returns this signal key that's used to remove this from the + // <ACE_Reactor>'s internal table. + + virtual int handle_signal (int, siginfo_t *, ucontext_t *); + // Called by the <Reactor> to dispatch the signal handler. + +private: + int sigkey_; + // Key for this signal handler (used to remove it). + + enum + { + ACE_HANDLER, // We're just wrapping an ACE_Event_Handler. + SIG_ACTION, // An ACE_Sig_Action. + C_FUNCTION // A normal C function. + } type_; + // Is this an external handler or an ACE handler? + + // = This should be a union, but C++ won't allow that because the + // <ACE_Sig_Action> has a constructor. + ACE_Sig_Action sa_; + // This is an external handler (ugh). + + ACE_Event_Handler *eh_; + // This is an ACE hander. + + ACE_Sig_Handler_Ex sig_func_; + // This is a normal C function. +}; + +// HPUX sucks big time! +#if !defined (HPUX) +class ACE_Export ACE_Sig_Handlers : public ACE_Sig_Handler + // = TITLE + // This is an alternative signal handling dispatcher for ACE. It + // allows a list of signal handlers to be registered for each + // signal. It also makes SA_RESTART the default mode. + // + // = DESCRIPTION + // Using this class a program can register one or more + // ACE_Event_Handler with the ACE_Sig_Handler in order to + // handle a designated <signum>. When a signal occurs that + // corresponds to this <signum>, the <handle_signal> methods of + // all the registered ACE_Event_Handlers are invoked + // automatically. +{ +public: + // = Registration and removal methods. + virtual int register_handler (int signum, + ACE_Event_Handler *new_sh, + ACE_Sig_Action *new_disp = 0, + ACE_Event_Handler **old_sh = 0, + ACE_Sig_Action *old_disp = 0); + // Add a new ACE_Event_Handler and a new sigaction associated with + // <signum>. Passes back the existing ACE_Event_Handler and its + // sigaction if pointers are non-zero. Returns -1 on failure and + // a <sigkey> that is >= 0 on success. + + virtual int remove_handler (int signum, + ACE_Sig_Action *new_disp = 0, + ACE_Sig_Action *old_disp = 0, + int sigkey = -1); + // Remove the ACE_Event_Handler currently associated with <signum>. + // Install the new disposition (if given) and return the previous + // disposition (if desired by the caller). Returns 0 on success and + // -1 if <signum> is invalid. + + // = Set/get the handler associated with a particular signal. + + virtual ACE_Event_Handler *handler (int signum); + // Return the head of the list of ACE_Sig_Handlers associated + // with SIGNUM. + + virtual ACE_Event_Handler *handler (int signum, ACE_Event_Handler *); + // Set a new ACE_Event_Handler that is associated with SIGNUM at the + // head of the list of signals. Return the existing handler that + // was at the head. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + static void dispatch (int signum, siginfo_t *, ucontext_t *); + // Callback routine registered with sigaction(2) that dispatches the + // handle_signal() method of all the pre-registered + // ACE_Event_Handlers for <signum> + + static int sigkey_; + // Keeps track of the id that uniquely identifies each registered + // signal handler. This id can be used to cancel a timer via the + // <remove_handler> method. + + static int third_party_sig_handler_; + // If this is > 0 then a 3rd party library has registered a + // handler... +}; +#endif /* HPUX */ + +#if defined (__ACE_INLINE__) +#include "ace/Signal.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_SIGNAL_HANDLER_H */ diff --git a/ace/Signal.i b/ace/Signal.i new file mode 100644 index 00000000000..e90f1431b38 --- /dev/null +++ b/ace/Signal.i @@ -0,0 +1,213 @@ +/* -*- C++ -*- */ +// $Id$ + +// Signal.i + +ACE_INLINE +ACE_Sig_Set::ACE_Sig_Set (sigset_t *ss) + : sigset_ (*ss) // Structure assignment +{ + ACE_TRACE ("ACE_Sig_Set::ACE_Sig_Set"); +} + +ACE_INLINE +ACE_Sig_Set::ACE_Sig_Set (int fill) +{ + ACE_TRACE ("ACE_Sig_Set::ACE_Sig_Set"); + if (fill) + ACE_OS::sigfillset (&this->sigset_); + else + ACE_OS::sigemptyset (&this->sigset_); +} + +ACE_INLINE +ACE_Sig_Set::~ACE_Sig_Set (void) +{ + ACE_TRACE ("ACE_Sig_Set::~ACE_Sig_Set"); + ACE_OS::sigemptyset (&this->sigset_); +} + +ACE_INLINE int +ACE_Sig_Set::empty_set (void) +{ + ACE_TRACE ("ACE_Sig_Set::empty_set"); + return ACE_OS::sigemptyset (&this->sigset_); +} + +ACE_INLINE int +ACE_Sig_Set::fill_set (void) +{ + ACE_TRACE ("ACE_Sig_Set::fill_set"); + return ACE_OS::sigfillset (&this->sigset_); +} + +ACE_INLINE int +ACE_Sig_Set::sig_add (int signo) +{ + ACE_TRACE ("ACE_Sig_Set::sig_add"); + return ACE_OS::sigaddset (&this->sigset_, signo); +} + +ACE_INLINE int +ACE_Sig_Set::sig_del (int signo) +{ + ACE_TRACE ("ACE_Sig_Set::sig_del"); + return ACE_OS::sigdelset (&this->sigset_, signo); +} + +ACE_INLINE int +ACE_Sig_Set::is_member (int signo) const +{ + ACE_TRACE ("ACE_Sig_Set::is_member"); + return ACE_OS::sigismember ((sigset_t *) &this->sigset_, signo); +} + +ACE_INLINE +ACE_Sig_Set::operator sigset_t *(void) +{ + ACE_TRACE ("ACE_Sig_Set::operator sigset_t *"); + return &this->sigset_; +} + +ACE_INLINE int +ACE_Sig_Action::flags (void) +{ + ACE_TRACE ("ACE_Sig_Action::flags"); + return this->sa_.sa_flags; +} + +ACE_INLINE void +ACE_Sig_Action::flags (int flags) +{ + ACE_TRACE ("ACE_Sig_Action::flags"); + this->sa_.sa_flags = flags; +} + +ACE_INLINE sigset_t * +ACE_Sig_Action::mask (void) +{ + ACE_TRACE ("ACE_Sig_Action::mask"); + return &this->sa_.sa_mask; +} + +ACE_INLINE void +ACE_Sig_Action::mask (sigset_t *ss) +{ + ACE_TRACE ("ACE_Sig_Action::mask"); + this->sa_.sa_mask = *ss; // Structure assignment +} + +ACE_INLINE ACE_SignalHandler +ACE_Sig_Action::handler (void) +{ + ACE_TRACE ("ACE_Sig_Action::handler"); + return ACE_SignalHandler (this->sa_.sa_handler); +} + +ACE_INLINE void +ACE_Sig_Action::handler (ACE_SignalHandler handler) +{ + ACE_TRACE ("ACE_Sig_Action::handler"); + this->sa_.sa_handler = ACE_SignalHandlerV (handler); +} + +ACE_INLINE void +ACE_Sig_Action::set (struct sigaction *sa) +{ + ACE_TRACE ("ACE_Sig_Action::set"); + this->sa_ = *sa; // Structure assignment. +} + +ACE_INLINE struct sigaction * +ACE_Sig_Action::get (void) +{ + ACE_TRACE ("ACE_Sig_Action::get"); + return &this->sa_; +} + +ACE_INLINE +ACE_Sig_Action::operator ACE_SIGACTION * () +{ + ACE_TRACE ("ACE_Sig_Action::operator ACE_SIGACTION *"); + return &this->sa_; +} + +ACE_INLINE +ACE_Sig_Action::ACE_Sig_Action (const ACE_Sig_Action &s) +{ + ACE_TRACE ("ACE_Sig_Action::ACE_Sig_Action"); + *this = s; // structure copy. +} + +ACE_INLINE int +ACE_Sig_Action::register_action (int signum, ACE_Sig_Action *oaction) +{ + ACE_TRACE ("ACE_Sig_Action::register_action"); + struct sigaction *sa = oaction == 0 ? 0 : oaction->get (); + + return ACE_OS::sigaction (signum, &this->sa_, sa); +} + +ACE_INLINE int +ACE_Sig_Action::retrieve_action (int signum) +{ + ACE_TRACE ("ACE_Sig_Action::retrieve_action"); + return ACE_OS::sigaction (signum, 0, &this->sa_); +} + +ACE_INLINE int +ACE_Sig_Action::restore_action (int signum, ACE_Sig_Action &oaction) +{ + ACE_TRACE ("ACE_Sig_Action::restore_action"); + this->sa_ = *oaction.get (); // Structure assignment + return ACE_OS::sigaction (signum, &this->sa_, 0); +} + +// Block out the signal MASK until the destructor is called. + +ACE_INLINE +ACE_Sig_Guard::ACE_Sig_Guard (ACE_Sig_Set *mask) +{ + ACE_TRACE ("ACE_Sig_Guard::ACE_Sig_Guard"); + // If MASK is 0 then block all signals! + if (mask == 0) + { + ACE_Sig_Set smask (1); + +#if 0 // defined (ACE_MT_SAFE) + ACE_OS::thr_sigsetmask (SIG_BLOCK, (sigset_t *) smask, (sigset_t *) + this->omask_); +#else + ACE_OS::sigprocmask (SIG_BLOCK, (sigset_t *) smask, (sigset_t *) + this->omask_); +#endif /* ACE_MT_SAFE */ + } + else +#if 0 // defined (ACE_MT_SAFE) + ACE_OS::thr_sigsetmask (SIG_BLOCK, (sigset_t *) *mask, (sigset_t *) + this->omask_); +#else + ACE_OS::sigprocmask (SIG_BLOCK, (sigset_t *) *mask, (sigset_t *) + this->omask_); +#endif /* ACE_MT_SAFE */ +} + +// Restore the signal mask. + +ACE_INLINE +ACE_Sig_Guard::~ACE_Sig_Guard (void) +{ + ACE_TRACE ("ACE_Sig_Guard::~ACE_Sig_Guard"); +#if 0 // defined (ACE_MT_SAFE) + ACE_OS::thr_sigsetmask (SIG_SETMASK, (sigset_t *) this->omask_, 0); +#else + ACE_OS::sigprocmask (SIG_SETMASK, (sigset_t *) this->omask_, 0); +#endif /* ACE_MT_SAFE */ +} + +ACE_INLINE int +ACE_Sig_Handler::in_range (int signum) +{ + ACE_TRACE ("ACE_Sig_Handler::in_range"); + return signum > 0 && signum < NSIG; +} diff --git a/ace/Singleton.cpp b/ace/Singleton.cpp new file mode 100644 index 00000000000..5d6a6e8ea31 --- /dev/null +++ b/ace/Singleton.cpp @@ -0,0 +1,78 @@ +// Singleton.cpp +// $Id$ + +#if !defined (ACE_SINGLETON_C) +#define ACE_SINGLETON_C + +#define ACE_BUILD_DLL +#include "ace/Singleton.h" +#include "ace/Synch_T.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Singleton.i" +#endif /* __ACE_INLINE__ */ + +template <class TYPE, class LOCK> void +ACE_Singleton<TYPE, LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Singleton<TYPE, LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + ACE_DEBUG ((LM_DEBUG, "instance_ = %x", this->instance_)); + ace_singleton_lock_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +} + +template <class TYPE, class LOCK> TYPE * +ACE_Singleton<TYPE, LOCK>::instance (void) +{ + ACE_TRACE ("ACE_Singleton::instance"); + +#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + // Pointer to the Singleton instance. This works around a bug with + // G++... + static TYPE *instance_ = 0; + + // Lock the creation of the singleton. This works around a + // "feature" of G++... ;-) + static LOCK ace_singleton_lock_; + // Perform the Double-Check pattern... + if (instance_ == 0) + { + ACE_GUARD_RETURN (LOCK, ace_mon, ace_singleton_lock_, 0); + + if (instance_ == 0) + ACE_NEW_RETURN (instance_, TYPE, 0); + } + + return instance_; +#else + + // Perform the Double-Check pattern... + if (ACE_Singleton<TYPE, LOCK>::instance_ == 0) + { + ACE_GUARD_RETURN (LOCK, ace_mon, (ACE_Singleton<TYPE, LOCK>::ace_singleton_lock_), 0); + + if (ACE_Singleton<TYPE, LOCK>::instance_ == 0) + ACE_NEW_RETURN ((ACE_Singleton<TYPE, LOCK>::instance_), TYPE, 0); + } + + return ACE_Singleton<TYPE, LOCK>::instance_; + +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ + +} + +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) +// Pointer to the Singleton instance. +template <class TYPE, class LOCK> TYPE * +ACE_Singleton<TYPE, LOCK>::instance_ = 0; + +// Lock the creation of the singleton. +template <class TYPE, class LOCK> LOCK +ACE_Singleton<TYPE, LOCK>::ace_singleton_lock_; +#endif /* !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ + +#endif /* ACE_SINGLETON_C */ diff --git a/ace/Singleton.h b/ace/Singleton.h new file mode 100644 index 00000000000..7761acf53c4 --- /dev/null +++ b/ace/Singleton.h @@ -0,0 +1,65 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Singleton.h +// +// = DESCRIPTION +// +// = AUTHOR +// Tim Harrison (harrison@cs.wustl.edu) and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_SINGLETON_H) +#define ACE_SINGLETON_H + +#include "ace/ACE.h" + +template <class TYPE, class LOCK> +class ACE_Singleton + // = TITLE + // A Singleton Adapter. + // + // = DESCRIPTION + // Uses the Adapter pattern to turn ordinary classes into + // Singletons optimized with the Double-Check pattern. +{ +public: + static TYPE *instance (void); + // Global access point to the Singleton. + + void dump (void) const; + // Dump the state of the object. + +protected: +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + static TYPE *instance_; + // Pointer to the Singleton instance. + + static LOCK ace_singleton_lock_; + // Lock the creation of the singleton. +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +}; + +#if defined (__ACE_INLINE__) +#include "ace/Singleton.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Singleton.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Singleton.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_SINGLETON_H */ + + diff --git a/ace/Singleton.i b/ace/Singleton.i new file mode 100644 index 00000000000..0cdd5148964 --- /dev/null +++ b/ace/Singleton.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Singleton.i diff --git a/ace/Stack.cpp b/ace/Stack.cpp new file mode 100644 index 00000000000..4f2a642244e --- /dev/null +++ b/ace/Stack.cpp @@ -0,0 +1,428 @@ +// Stack.cpp +// $Id$ + +#if !defined (ACE_STACK_C) +#define ACE_STACK_C + +#define ACE_BUILD_DLL +#include "ace/Stack.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Stack.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Bounded_Stack) + +template <class T> void +ACE_Bounded_Stack<T>::dump (void) const +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::dump"); +} + +template<class T> +ACE_Bounded_Stack<T>::ACE_Bounded_Stack (size_t size) + : top_ (0), + size_ (size) +{ + ACE_NEW (this->stack_, T[size]); + + ACE_TRACE ("ACE_Bounded_Stack<T>::ACE_Bounded_Stack"); +} + +template<class T> +ACE_Bounded_Stack<T>::ACE_Bounded_Stack (const ACE_Bounded_Stack<T> &s) + : top_ (s.top_), + size_ (s.size_) +{ + ACE_NEW (this->stack_, T[s.size_]); + + ACE_TRACE ("ACE_Bounded_Stack<T>::ACE_Bounded_Stack"); + + for (size_t i = 0; i < this->top_; i++) + this->stack_[i] = s.stack_[i]; +} + +template<class T> void +ACE_Bounded_Stack<T>::operator= (const ACE_Bounded_Stack<T> &s) +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::operator="); + if (&s == this) + return; + else if (this->size_ < s.size_) + { + delete [] this->stack_; + ACE_NEW (this->stack_, T[s.size_]); + } + this->top_ = s.top_; + + for (size_t i = 0; i < this->top_; i++) + this->stack_[i] = s.stack_[i]; +} + +template<class T> +ACE_Bounded_Stack<T>::~ACE_Bounded_Stack (void) +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::~ACE_Bounded_Stack"); + delete [] this->stack_; +} + +// ---------------------------------------- + +ACE_ALLOC_HOOK_DEFINE(ACE_Fixed_Stack) + +template <class T, size_t SIZE> void +ACE_Fixed_Stack<T, SIZE>::dump (void) const +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::dump"); +} + +template<class T, size_t SIZE> +ACE_Fixed_Stack<T, SIZE>::ACE_Fixed_Stack (void) + : top_ (0), + size_ (SIZE) +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::ACE_Fixed_Stack"); +} + +template<class T, size_t SIZE> +ACE_Fixed_Stack<T, SIZE>::ACE_Fixed_Stack (const ACE_Fixed_Stack<T, SIZE> &s) + : top_ (s.top_), + size_ (s.size_) +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::ACE_Fixed_Stack"); + for (size_t i = 0; i < this->top_; i++) + this->stack_[i] = s.stack_[i]; +} + +template<class T, size_t SIZE> void +ACE_Fixed_Stack<T, SIZE>::operator= (const ACE_Fixed_Stack<T, SIZE> &s) +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::operator="); + if (&s == this) + return; + this->top_ = s.top_; + + for (size_t i = 0; i < this->top_; i++) + this->stack_[i] = s.stack_[i]; +} + +template<class T, size_t SIZE> +ACE_Fixed_Stack<T, SIZE>::~ACE_Fixed_Stack (void) +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::~ACE_Fixed_Stack"); + delete [] this->stack_; +} + +//---------------------------------------- + +template<class T> +class ACE_Stack_Node +{ +friend class ACE_Unbounded_Stack<T>; +private: +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + // = Only use a free list if the compiler supports static data + // members... + + void *operator new (size_t bytes); + void operator delete (void *ptr); + + // Returns all dynamic memory on the free list to the free store. + static void free_all_nodes (void); + + static ACE_Stack_Node<T> *free_list_; + // Head of the free list of Nodes used to speed up allocation. +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ + + ACE_Stack_Node (T i, ACE_Stack_Node<T> *n); + ACE_Stack_Node (void); + + ACE_Stack_Node<T> *next_; + T item_; +}; + +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) +/* static */ +template<class T> ACE_Stack_Node<T> * +ACE_Stack_Node<T>::free_list_ = 0; + +template<class T> void * +ACE_Stack_Node<T>::operator new (size_t bytes) +{ + ACE_TRACE ("ACE_Stack_Node<T>::operator new"); + ACE_Stack_Node<T> *temp = ACE_Stack_Node<T>::free_list_; + + if (temp) + ACE_Stack_Node<T>::free_list_ = ACE_Stack_Node<T>::free_list_->next_; + else + temp = (ACE_Stack_Node<T> *) new char[bytes]; + + return temp; +} + +template<class T> void +ACE_Stack_Node<T>::operator delete (void *ptr) +{ + ACE_TRACE ("ACE_Stack_Node<T>::operator delete"); + ((ACE_Stack_Node<T> *) ptr)->next_ = ACE_Stack_Node<T>::free_list_; + ACE_Stack_Node<T>::free_list_ = (ACE_Stack_Node<T> *) ptr; +} + +template<class T> void +ACE_Stack_Node<T>::free_all_nodes (void) +{ + ACE_TRACE ("ACE_Stack_Node<T>::free_all_nodes"); + + while (ACE_Stack_Node<T>::free_list_) + { + ACE_Stack_Node<T> *temp = ACE_Stack_Node<T>::free_list_; + ACE_Stack_Node<T>::free_list_ = ACE_Stack_Node<T>::free_list_->next_; + ::delete temp; + } +} + +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ + +template<class T> +ACE_Stack_Node<T>::ACE_Stack_Node (T i, ACE_Stack_Node<T> *n) + : next_ (n), + item_ (i) +{ + ACE_TRACE ("ACE_Stack_Node<T>::ACE_Stack_Node"); +} + +template<class T> +ACE_Stack_Node<T>::ACE_Stack_Node (void) + : next_ (0) +{ + ACE_TRACE ("ACE_Stack_Node<T>::ACE_Stack_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Stack) + +template <class T> void +ACE_Unbounded_Stack<T>::dump (void) const +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::dump"); +} + +template<class T> +ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack (void) + : head_ (0) +{ + ACE_NEW (this->last_resort_, ACE_Stack_Node<T>); + ACE_TRACE ("ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack"); +} + +template<class T> void +ACE_Unbounded_Stack<T>::delete_all_nodes (void) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::delete_all_nodes"); + while (this->head_ != 0) + { + ACE_Stack_Node<T> *temp = this->head_; + this->head_ = this->head_->next_; + delete temp; + } + + delete this->last_resort_; + this->last_resort_ = 0; +} + +template<class T> void +ACE_Unbounded_Stack<T>::copy_all_nodes (const ACE_Unbounded_Stack<T> &s) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::copy_all_nodes"); + // Push all of <s>'s nodes onto our stack (this puts them in the + // reverse order). + ACE_Stack_Node<T> *temp; + + for (temp = s.head_; + temp != 0; + temp = temp->next_) + { + if (!this->is_full ()) + this->push (temp->item_); + else + break; + } + + // Reverse the order of our stack. + + ACE_Stack_Node<T> *prev = 0; + + for (temp = this->head_; temp != 0; ) + { + ACE_Stack_Node<T> *next = temp->next_; + + temp->next_ = prev; + prev = temp; + temp = next; + } + + this->head_ = prev; +} + +template<class T> +ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack (const ACE_Unbounded_Stack<T> &s) + : head_ (0) +{ + ACE_NEW (this->last_resort_, ACE_Stack_Node<T>); + + ACE_TRACE ("ACE_Unbounded_Stack<T>::ACE_Unbounded_Stack"); + this->copy_all_nodes (s); +} + +template<class T> void +ACE_Unbounded_Stack<T>::operator= (const ACE_Unbounded_Stack<T> &s) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::operator="); + if (this == &s) + return; + + this->delete_all_nodes (); + this->copy_all_nodes (s); +} + +template<class T> +ACE_Unbounded_Stack<T>::~ACE_Unbounded_Stack (void) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::~ACE_Unbounded_Stack"); + this->delete_all_nodes (); +} + +template<class T> void +ACE_Unbounded_Stack<T>::push (const T &new_item) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::push"); + + ACE_Stack_Node<T> *temp = new ACE_Stack_Node<T> (new_item, this->head_); + + if (temp == 0) + { + temp = this->last_resort_; + this->last_resort_ = 0; + } + + this->head_ = temp; +} + +template<class T> void +ACE_Unbounded_Stack<T>::pop (T &item) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::pop"); + item = this->head_->item_; + ACE_Stack_Node<T> *temp = this->head_; + this->head_ = this->head_->next_; + + // Restore the node of last resort if necessary. + if (this->last_resort_ == 0) + this->last_resort_ = temp; + else + delete temp; +} + +template<class T> void +ACE_Unbounded_Stack<T>::delete_free_list (void) +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::delete_free_list"); +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + ACE_Stack_Node<T>::free_all_nodes (); +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +} + +template<class T> +class ACE_Queue_Node +{ +friend class ACE_Unbounded_Queue<T>; + ACE_Queue_Node (T i, ACE_Queue_Node<T> *n); + + ACE_Queue_Node<T> *next_; + T item_; +}; + +template<class T> +ACE_Queue_Node<T>::ACE_Queue_Node (T i, ACE_Queue_Node<T> *n) + : next_ (n), + item_ (i) +{ + ACE_TRACE ("ACE_Queue_Node<T>::ACE_Queue_Node"); +} + +template <class TYPE> +ACE_Unbounded_Queue<TYPE>::ACE_Unbounded_Queue (void) + : head_ (0), + tail_ (0), + cur_size_ (0) +{ + ACE_TRACE ("ACE_Unbounded_Queue<TYPE>::ACE_Unbounded_Queue (void)"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Unbounded_Queue) + +template <class TYPE> void +ACE_Unbounded_Queue<TYPE>::dump (void) const +{ + ACE_TRACE ("ACE_Unbounded_Queue<TYPE>::dump"); +} + +template <class TYPE> +ACE_Unbounded_Queue<TYPE>::~ACE_Unbounded_Queue (void) +{ + ACE_TRACE ("ACE_Unbounded_Queue<TYPE>::~ACE_Unbounded_Queue (void)"); + ACE_Queue_Node<TYPE> *temp = head_; + while (temp != 0) + { + head_ = head_->next_; + delete temp; + temp = head_; + this->cur_size_--; + } +} + +template <class TYPE> int +ACE_Unbounded_Queue<TYPE>::enqueue (const TYPE &new_item) +{ + ACE_TRACE ("ACE_Unbounded_Queue<TYPE>::enqueue (const TYPE& new_item)"); + + ACE_Queue_Node<TYPE> *temp = new ACE_Queue_Node<TYPE> (new_item, 0); + + if (temp == 0) + return -1; + + if (head_ == 0) + head_ = tail_ = temp; + else + { + tail_->next_ = temp; + tail_ = temp; + } + + ++this->cur_size_; + + return 0; +} + +template <class TYPE> int +ACE_Unbounded_Queue<TYPE>::dequeue (TYPE &item) +{ + ACE_TRACE ("ACE_Unbounded_Queue<TYPE>::dequeue (TYPE *&item)"); + + if (head_ == 0) + return -1; + + item = head_->item_; + ACE_Queue_Node<TYPE> *temp = head_; + head_ = head_->next_; + delete temp; + --this->cur_size_; + return 0; +} + +template <class TYPE> int +ACE_Unbounded_Queue<TYPE>::size (void) const +{ + return this->cur_size_; +} + +#endif /* ACE_STACK_C */ diff --git a/ace/Stack.h b/ace/Stack.h new file mode 100644 index 00000000000..6b7e9ad7ed8 --- /dev/null +++ b/ace/Stack.h @@ -0,0 +1,280 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Stack.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_STACK_H) +#define ACE_STACK_H + +#include "ace/ACE.h" + +template <class T> +class ACE_Bounded_Stack + // = TITLE + // Implement a generic LIFO abstract data type. + // + // = DESCRIPTION + // This implementation of a Stack uses a bounded array + // that is allocated dynamically. +{ +public: + // = Initialization, assignemnt, and termination methods. + ACE_Bounded_Stack (size_t size); + // Initialize a new stack so that it is empty. + + ACE_Bounded_Stack (const ACE_Bounded_Stack<T> &s); + // The copy constructor (performs initialization). + + void operator= (const ACE_Bounded_Stack<T> &s); + // Assignment operator (performs assignment). + + ~ACE_Bounded_Stack (void); + // Perform actions needed when stack goes out of scope. + + // = Classic Stack operations. + + void push (const T &new_item); + // Place a new item on top of the stack. Does not check if the + // stack is full. + + void pop (T &item); + // Remove and return the top stack item. Does not check if stack + // is full. + + void top (T &item) const; + // Return top stack item without removing it. Does not check if + // stack is empty. + + // = Check boundary conditions for Stack operations. + + int is_empty (void) const; + // Returns 1 if the stack is empty, otherwise returns 0. + + int is_full (void) const; + // Returns 1 if the stack is full, otherwise returns 0. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + size_t size_; + // Size of the dynamically allocated data. + + size_t top_; + // Keeps track of the current top of stack. + + T *stack_; + // Holds the stack's contents. +}; + +//---------------------------------------- + +template <class T, size_t SIZE> +class ACE_Fixed_Stack + // = TITLE + // Implement a generic LIFO abstract data type. + // + // = DESCRIPTION + // This implementation of a Stack uses a fixed array + // with the size fixed at instantiation time. +{ +public: + // = Initialization, assignemnt, and termination methods. + ACE_Fixed_Stack (void); + // Initialize a new stack so that it is empty. + + ACE_Fixed_Stack (const ACE_Fixed_Stack<T, SIZE> &s); + // The copy constructor (performs initialization). + + void operator= (const ACE_Fixed_Stack<T, SIZE> &s); + // Assignment operator (performs assignment). + + ~ACE_Fixed_Stack (void); + // Perform actions needed when stack goes out of scope. + + // = Classic Stack operations. + + void push (const T &new_item); + // Place a new item on top of the stack. Does not check if the + // stack is full. + + void pop (T &item); + // Remove and return the top stack item. Does not check if stack + // is full. + + void top (T &item) const; + // Return top stack item without removing it. Does not check if + // stack is empty. + + // = Check boundary conditions for Stack operations. + + int is_empty (void) const; + // Returns 1 if the stack is empty, otherwise returns 0. + + int is_full (void) const; + // Returns 1 if the stack is full, otherwise returns 0. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + size_t size_; + // Size of the dynamically allocated data. + + size_t top_; + // Keeps track of the current top of stack. + + T stack_[SIZE]; + // Holds the stack's contents. +}; + +//---------------------------------------- + +// Forward declaration (use the "Cheshire Cat" approach to information +// hiding). +template <class T> +class ACE_Stack_Node; + +template <class T> +class ACE_Unbounded_Stack + // = TITLE + // Implement a generic LIFO abstract data type. + // + // = DESCRIPTION + // This implementation of an unbounded Stack uses a linked list. +{ +public: + // = Initialization, assignemnt, and termination methods. + ACE_Unbounded_Stack (void); + // Initialize a new stack so that it is empty. + + ACE_Unbounded_Stack (const ACE_Unbounded_Stack<T> &s); + // The copy constructor (performs initialization). + + void operator= (const ACE_Unbounded_Stack<T> &s); + // Assignment operator (performs assignment). + + ~ACE_Unbounded_Stack (void); + // Perform actions needed when stack goes out of scope. + + // = Classic Stack operations. + + void push (const T &new_item); + // Place a new item on top of the stack. Does not check if the + // stack is full. + + void pop (T &item); + // Remove and return the top stack item. Does not check if stack + // is full. + + void top (T &item) const; + // Return top stack item without removing it. Does not check if + // stack is empty. + + // = Check boundary conditions for Stack operations. + + int is_empty (void) const; + // Returns 1 if the stack is empty, otherwise returns 0. + + int is_full (void) const; + // Returns 1 if the stack is full, otherwise returns 0. + + static void delete_free_list (void); + // Returns all dynamic memory on the free list to the free store. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + void delete_all_nodes (void); + // Delete all the nodes in the stack. + + void copy_all_nodes (const ACE_Unbounded_Stack<T> &s); + // Copy all nodes from <s> to <this>. + + ACE_Stack_Node<T> *head_; + // Head of the linked list of Nodes. + + ACE_Stack_Node<T> *last_resort_; + // Use this node when all memory is exhausted... +}; + +// Forward declaration (use the "Cheshire Cat" approach to information +// hiding). +template <class T> +class ACE_Queue_Node; + +template <class TYPE> +class ACE_Unbounded_Queue + // = TITLE + // A Queue of "infinite" length. + + // = DESCRIPTION + // Implemented using dynamic memory... +{ +public: + ACE_Unbounded_Queue (void); + // construction. + + ~ACE_Unbounded_Queue (void); + // construction. + + int enqueue (const TYPE &new_item); + // Returns 0 on success -1 on failure. + + int dequeue (TYPE &item); + // Returns 0 on success -1 if nothing was found. + + int size (void) const; + // The size of the queue + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_Queue_Node<TYPE> *head_; + // Head of the Queue. + + ACE_Queue_Node<TYPE> *tail_; + // Tail of the Queue. + + size_t cur_size_; + // Current size of the queue. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Stack.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Stack.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Stack.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_STACK_H */ diff --git a/ace/Stack.i b/ace/Stack.i new file mode 100644 index 00000000000..7c34c0efa22 --- /dev/null +++ b/ace/Stack.i @@ -0,0 +1,100 @@ +/* -*- C++ -*- */ +// $Id$ + +// Stack.i + +template <class T> ACE_INLINE void +ACE_Bounded_Stack<T>::push (const T &new_item) +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::push"); + this->stack_[this->top_++] = new_item; +} + +template <class T> ACE_INLINE void +ACE_Bounded_Stack<T>::pop (T &item) +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::pop"); + item = this->stack_[--this->top_]; +} + +template <class T> ACE_INLINE void +ACE_Bounded_Stack<T>::top (T &item) const +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::top"); + item = this->stack_[this->top_ - 1]; +} + +template <class T> ACE_INLINE int +ACE_Bounded_Stack<T>::is_empty (void) const +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::is_empty"); + return this->top_ == 0; +} + +template <class T> ACE_INLINE int +ACE_Bounded_Stack<T>::is_full (void) const +{ + ACE_TRACE ("ACE_Bounded_Stack<T>::is_full"); + return this->top_ >= this->size_; +} + +//---------------------------------------- + +template <class T, size_t SIZE> ACE_INLINE void +ACE_Fixed_Stack<T, SIZE>::push (const T &new_item) +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::push"); + this->stack_[this->top_++] = new_item; +} + +template <class T, size_t SIZE> ACE_INLINE void +ACE_Fixed_Stack<T, SIZE>::pop (T &item) +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::pop"); + item = this->stack_[--this->top_]; +} + +template <class T, size_t SIZE> ACE_INLINE void +ACE_Fixed_Stack<T, SIZE>::top (T &item) const +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::top"); + item = this->stack_[this->top_ - 1]; +} + +template <class T, size_t SIZE> ACE_INLINE int +ACE_Fixed_Stack<T, SIZE>::is_empty (void) const +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::is_empty"); + return this->top_ == 0; +} + +template <class T, size_t SIZE> ACE_INLINE int +ACE_Fixed_Stack<T, SIZE>::is_full (void) const +{ + ACE_TRACE ("ACE_Fixed_Stack<T, SIZE>::is_full"); + return this->top_ >= this->size_; +} + +//---------------------------------------- + +template <class T> ACE_INLINE void +ACE_Unbounded_Stack<T>::top (T &item) const +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::top"); + item = this->head_->item_; +} + +template <class T> ACE_INLINE int +ACE_Unbounded_Stack<T>::is_empty (void) const +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::is_empty"); + return this->head_ == 0; +} + +template <class T> ACE_INLINE int +ACE_Unbounded_Stack<T>::is_full (void) const +{ + ACE_TRACE ("ACE_Unbounded_Stack<T>::is_full"); + return this->last_resort_ == 0; +} + diff --git a/ace/Strategies.cpp b/ace/Strategies.cpp new file mode 100644 index 00000000000..fc85d67e150 --- /dev/null +++ b/ace/Strategies.cpp @@ -0,0 +1,504 @@ +// Strategies.cpp +// $Id$ + +#if !defined (ACE_STRATEGIES_C) +#define ACE_STRATEGIES_C + +#define ACE_BUILD_DLL +#include "ace/Strategies.h" + +#define SH SVC_HANDLER +#define PR_AC_1 ACE_PEER_ACCEPTOR_1 +#define PR_AC_2 ACE_PEER_ACCEPTOR_2 +#define PR_AD ACE_PEER_ACCEPTOR_ADDR + +ACE_ALLOC_HOOK_DEFINE(ACE_Singleton_Strategy) + +template <class SH> void +ACE_Singleton_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Singleton_Strategy<SH>::dump"); +} + +template <class SH> int +ACE_Singleton_Strategy<SH>::open (SVC_HANDLER *sh, + ACE_Thread_Manager *) +{ + ACE_TRACE ("ACE_Singleton_Strategy<SH>::open"); + if (this->svc_handler_ != 0) + delete this->svc_handler_; + + this->svc_handler_ = sh; + return 0; +} + +template <class SH> +ACE_Singleton_Strategy<SH>::ACE_Singleton_Strategy (SVC_HANDLER *sh, + ACE_Thread_Manager *tm) + : svc_handler_ (0) +{ + ACE_TRACE ("ACE_Singleton_Strategy<SH>::ACE_Singleton_Strategy"); + this->open (sh, tm); +} + +template <class SH> +ACE_Singleton_Strategy<SH>::~ACE_Singleton_Strategy (void) +{ + ACE_TRACE ("ACE_Singleton_Strategy<SH>::~ACE_Singleton_Strategy"); + delete this->svc_handler_; +} + +// Create a Singleton SVC_HANDLER by always returning the same +// SVC_HANDLER. + +template <class SH> SVC_HANDLER * +ACE_Singleton_Strategy<SH>::make_svc_handler (void) +{ + ACE_TRACE ("ACE_Singleton_Strategy<SH>::make_svc_handler"); + return this->svc_handler_; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Creation_Strategy) + +template <class SH> void +ACE_Creation_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Creation_Strategy<SH>::dump"); +} + +template <class SH> int +ACE_Creation_Strategy<SH>::open (ACE_Thread_Manager *thr_mgr) +{ + ACE_TRACE ("ACE_Creation_Strategy<SH>::open"); + this->thr_mgr_ = thr_mgr; + return 0; +} + + +template <class SH> +ACE_Creation_Strategy<SH>::ACE_Creation_Strategy (ACE_Thread_Manager *thr_mgr) +{ + ACE_TRACE ("ACE_Creation_Strategy<SH>::ACE_Creation_Strategy"); + this->open (thr_mgr); +} + +// Default behavior is to make a new SVC_HANDLER, passing in the +// Thread_Manager (if any). + +template <class SH> SH * +ACE_Creation_Strategy<SH>::make_svc_handler (void) +{ + ACE_TRACE ("ACE_Creation_Strategy<SH>::make_svc_handler"); + return new SH (this->thr_mgr_); +} + +template <class SH> +ACE_Creation_Strategy<SH>::~ACE_Creation_Strategy (void) +{ + ACE_TRACE ("ACE_Creation_Strategy<SH>::~ACE_Creation_Strategy"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_DLL_Strategy) + +template <class SH> void +ACE_DLL_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_DLL_Strategy<SH>::dump"); +} + +template <class SH> int +ACE_DLL_Strategy<SH>::open (const char svc_dll_info[], + ACE_Service_Config *svc_config, + ACE_Thread_Manager *thr_mgr) +{ + ACE_TRACE ("ACE_DLL_Strategy<SH>::open"); + this->inherited::open (thr_mgr); + this->svc_config_ = svc_config; + return 0; +} + +template <class SH> +ACE_DLL_Strategy<SH>::ACE_DLL_Strategy (const char svc_dll_info[], + ACE_Service_Config *sc, + ACE_Thread_Manager *thr_mgr) +{ + ACE_TRACE ("ACE_DLL_Strategy<SH>::ACE_DLL_Strategy"); + if (this->open (svc_dll_info, sc, thr_mgr) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "open")); +} + +template <class SH> +ACE_DLL_Strategy<SH>::ACE_DLL_Strategy (void) +{ + ACE_TRACE ("ACE_DLL_Strategy<SH>::ACE_DLL_Strategy"); +} + +// Create a SVC_HANDLER by dynamically linking it from a DLL. + +template <class SH> SH * +ACE_DLL_Strategy<SH>::make_svc_handler (void) +{ + ACE_TRACE ("ACE_DLL_Strategy<SH>::make_svc_handler"); + // Open the shared library. + void *handle = (void *) ACE_OS::dlopen (this->shared_library_); + + // Extract the factory function. + SH *(*factory)(void) = (SH *(*)(void)) ACE_OS::dlsym (handle, + this->factory_function_); + + // Call the factory function to obtain the new SVC_Handler (should + // use RTTI here when it becomes available...) + SH *svc_handler = (*factory)(); + + if (svc_handler != 0) + { + // Create an ACE_Service_Record containing the SVC_Handler and + // insert into this->svc_config_->svc_rep; + + // @@ This remains to be implemented... + // @@ Somehow, we need to deal with this->thr_mgr_... + } + + return svc_handler; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Concurrency_Strategy) + +template <class SH> void +ACE_Concurrency_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Concurrency_Strategy<SH>::dump"); +} + +// Default behavior is to activate the SVC_HANDLER by calling it's +// open() method, which allows the SVC_HANDLER to determine its own +// concurrency strategy. + +template <class SH> int +ACE_Concurrency_Strategy<SH>::activate_svc_handler (SH *svc_handler, + void *arg) +{ + ACE_TRACE ("ACE_Concurrency_Strategy<SH>::activate_svc_handler"); + // Delegate control to the application-specific service + // handler. + + if (svc_handler->open (arg) == -1) + { + // Close down handler to avoid resource leaks. + svc_handler->close (0); + return -1; + } + else + return 0; +} + +template <class SH> +ACE_Concurrency_Strategy<SH>::~ACE_Concurrency_Strategy (void) +{ + ACE_TRACE ("ACE_Concurrency_Strategy<SH>::~ACE_Concurrency_Strategy"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Strategy) + +template <class SH> void +ACE_Thread_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Thread_Strategy<SH>::dump"); +} + +template <class SH> int +ACE_Thread_Strategy<SH>::open (ACE_Thread_Manager *thr_mgr, + long thr_flags, + int n_threads) +{ + ACE_TRACE ("ACE_Thread_Strategy<SH>::open"); + this->thr_mgr_ = thr_mgr; + this->n_threads_ = n_threads; + this->thr_flags_ = thr_flags; + + // Must have a thread manager! + if (this->thr_mgr_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "error: must have a non-NULL thread manager\n"), -1); + else + return 0; +} + +template <class SH> +ACE_Thread_Strategy<SH>::ACE_Thread_Strategy (ACE_Thread_Manager *thr_mgr, + long thr_flags, + int n_threads) +{ + ACE_TRACE ("ACE_Thread_Strategy<SH>::ACE_Thread_Strategy"); + this->open (thr_mgr, thr_flags, n_threads); +} + +template <class SH> +ACE_Thread_Strategy<SH>::ACE_Thread_Strategy (void) +{ + ACE_TRACE ("ACE_Thread_Strategy<SH>::ACE_Thread_Strategy"); +} + +template <class SH> +ACE_Thread_Strategy<SH>::~ACE_Thread_Strategy (void) +{ + ACE_TRACE ("ACE_Thread_Strategy<SH>::~ACE_Thread_Strategy"); +} + +template <class SH> int +ACE_Thread_Strategy<SH>::activate_svc_handler (SH *svc_handler, + void *arg) +{ + ACE_TRACE ("ACE_Thread_Strategy<SH>::activate_svc_handler"); + // Call up to our parent to do the SVC_HANDLER initialization. + if (this->inherited::activate_svc_handler (svc_handler, arg) == -1) + return -1; + else + // Turn the <svc_handler> into an active object (if it isn't + // already one as a result of the first activation...) + return svc_handler->activate (this->thr_flags_, this->n_threads_); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Accept_Strategy) + +template <class SH, PR_AC_1> void +ACE_Accept_Strategy<SH, PR_AC_2>::dump (void) const +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::dump"); +} + +template <class SH, PR_AC_1> int +ACE_Accept_Strategy<SH, PR_AC_2>::open (const PR_AD &local_addr, + int restart) +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::open"); + return this->peer_acceptor_.open (local_addr, restart); +} + +template <class SH, PR_AC_1> +ACE_Accept_Strategy<SH, PR_AC_2>::ACE_Accept_Strategy (const PR_AD &local_addr, + int restart) +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::ACE_Accept_Strategy"); + if (this->open (local_addr, restart) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "open")); +} + +template <class SH, PR_AC_1> +ACE_Accept_Strategy<SH, PR_AC_2>::ACE_Accept_Strategy (void) +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::ACE_Accept_Strategy"); +} + +template <class SH, PR_AC_1> int +ACE_Accept_Strategy<SH, PR_AC_2>::accept_svc_handler (SH *svc_handler) +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::accept_svc_handler"); + if (this->peer_acceptor_.accept (*svc_handler) == -1) + { + svc_handler->close (0); + return -1; + } + else + return 0; +} + +template <class SH, PR_AC_1> ACE_HANDLE +ACE_Accept_Strategy<SH, PR_AC_2>::get_handle (void) const +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::get_handle"); + return this->peer_acceptor_.get_handle (); +} + +template <class SH, PR_AC_1> ACE_PEER_ACCEPTOR & +ACE_Accept_Strategy<SH, PR_AC_2>::acceptor (void) const +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::acceptor"); + return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; +} + +template <class SH, PR_AC_1> +ACE_Accept_Strategy<SH, PR_AC_2>::~ACE_Accept_Strategy (void) +{ + ACE_TRACE ("ACE_Accept_Strategy<SH, PR_AC_2>::~ACE_Accept_Strategy"); + if (this->peer_acceptor_.close () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "close")); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Process_Strategy) + +template <class SH> void +ACE_Process_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Process_Strategy<SH>::dump"); +} + +template <class SH> int +ACE_Process_Strategy<SH>::open (int n_processes) +{ + ACE_TRACE ("ACE_Process_Strategy<SH>::open"); + this->n_processes_ = n_processes; + + return 0; +} + +template <class SH> +ACE_Process_Strategy<SH>::ACE_Process_Strategy (int n_processes) +{ + ACE_TRACE ("ACE_Process_Strategy<SH>::ACE_Process_Strategy"); + this->open (thr_mgr, thr_flags, n_threads); +} + +template <class SH> +ACE_Process_Strategy<SH>::ACE_Process_Strategy (void) +{ + ACE_TRACE ("ACE_Process_Strategy<SH>::ACE_Process_Strategy"); +} + +template <class SH> +ACE_Process_Strategy<SH>::~ACE_Process_Strategy (void) +{ + ACE_TRACE ("ACE_Process_Strategy<SH>::~ACE_Process_Strategy"); +} + +template <class SH> int +ACE_Process_Strategy<SH>::activate_svc_handler (SH *svc_handler, + void *arg) +{ + ACE_TRACE ("ACE_Process_Strategy<SH>::activate_svc_handler"); + switch (ACE_OS::fork ()) + { + case -1: + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "fork"), -1); + /* NOTREACHED */ + case 0: // In child process. + // Call up to our ancestor in the inheritance to do the + // SVC_HANDLER initialization. + return this->inherited::activate_svc_handler (svc_handler, arg); + /* NOTREACHED */ + default: // In parent process. + return 0; + } +} + +template <class SH> +ACE_Scheduling_Strategy<SH>::ACE_Scheduling_Strategy (SH *scheduler) + : scheduler_ (scheduler), + delete_scheduler_ (0) +{ + ACE_TRACE ("ACE_Scheduling_Strategy<SH>::ACE_Scheduling_Strategy"); + + if (this->scheduler_ == 0) + { + // Create a new SVC_HANDLER and assign the global Thread_Manager + // and Reactor to it... + ACE_NEW (this->scheduler_, SH); + + if (this->scheduler_->thr_mgr () == 0) + this->scheduler_->thr_mgr (ACE_Service_Config::thr_mgr ()); + + if (this->scheduler_->reactor () == 0) + this->scheduler_->reactor (ACE_Service_Config::reactor ()); + + this->delete_scheduler_ = 1; + } +} + +template <class SH> +ACE_Scheduling_Strategy<SH>::~ACE_Scheduling_Strategy (void) +{ + ACE_TRACE ("ACE_Scheduling_Strategy<SH>::~ACE_Scheduling_Strategy"); + + if (this->delete_scheduler_) + this->scheduler_->destroy (); +} + +template <class SH> void +ACE_Scheduling_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Scheduling_Strategy<SH>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "scheduler_ = %x", this->scheduler_)); + ACE_DEBUG ((LM_DEBUG, "\ndelete_scheduler_ = %d", this->delete_scheduler_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SH> int +ACE_Scheduling_Strategy<SH>::suspend (void) +{ + ACE_TRACE ("ACE_Scheduling_Strategy<SH>::suspend"); + return -1; +} + +template <class SH> int +ACE_Scheduling_Strategy<SH>::resume (void) +{ + ACE_TRACE ("ACE_Scheduling_Strategy<SH>::resume"); + return -1; +} + +template <class SH> +ACE_Schedule_All_Reactive_Strategy<SH>::ACE_Schedule_All_Reactive_Strategy (SH *scheduler) + : ACE_Scheduling_Strategy<SH> (scheduler) +{ + ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SH>::ACE_Schedule_All_Reactive_Strategy"); +} + +template <class SH> int +ACE_Schedule_All_Reactive_Strategy<SH>::suspend (void) +{ + ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SH>::suspend"); + return this->scheduler_->reactor ()->suspend_handlers (); +} + +template <class SH> void +ACE_Schedule_All_Reactive_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SH>::dump"); + + ACE_Scheduling_Strategy<SH>::dump (); +} + +template <class SVC_HANDLER> int +ACE_Schedule_All_Reactive_Strategy<SH>::resume (void) +{ + ACE_TRACE ("ACE_Schedule_All_Reactive_Strategy<SH>::resume"); + return this->scheduler_->reactor ()->resume_handlers (); +} + +template <class SH> +ACE_Schedule_All_Threaded_Strategy<SH>::ACE_Schedule_All_Threaded_Strategy (SH *scheduler) + : ACE_Scheduling_Strategy<SH> (scheduler) +{ + ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SH>::ACE_Schedule_All_Threaded_Strategy"); +} + +template <class SH> int +ACE_Schedule_All_Threaded_Strategy<SH>::suspend (void) +{ + ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SH>::suspend"); + return this->scheduler_->thr_mgr ()->suspend_all (); +} + +template <class SVC_HANDLER> int +ACE_Schedule_All_Threaded_Strategy<SH>::resume (void) +{ + ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SH>::resume"); + return this->scheduler_->thr_mgr ()->resume_all (); +} + +template <class SH> void +ACE_Schedule_All_Threaded_Strategy<SH>::dump (void) const +{ + ACE_TRACE ("ACE_Schedule_All_Threaded_Strategy<SH>::dump"); + + ACE_Scheduling_Strategy<SH>::dump (); +} + +#undef SH +#undef PR_AC_1 +#undef PR_AC_2 +#undef PR_AD + +#endif /* ACE_STRATEGIES_C */ diff --git a/ace/Strategies.h b/ace/Strategies.h new file mode 100644 index 00000000000..f8677201f5f --- /dev/null +++ b/ace/Strategies.h @@ -0,0 +1,445 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE_Strategies.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_STRATEGIES_H) +#define ACE_STRATEGIES_H + +#include "ace/Service_Config.h" + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +#define ACE_PEER_ACCEPTOR_1 class PEER_ACCEPTOR +#define ACE_PEER_ACCEPTOR_2 PEER_ACCEPTOR +#define ACE_PEER_ACCEPTOR PEER_ACCEPTOR +#define ACE_PEER_ACCEPTOR_ADDR PEER_ACCEPTOR::PEER_ADDR +#else +#define ACE_PEER_ACCEPTOR_1 class PEER_ACCEPTOR, class PEER_ADDR +#define ACE_PEER_ACCEPTOR_2 PEER_ACCEPTOR, PEER_ADDR +#define ACE_PEER_ACCEPTOR PEER_ACCEPTOR +#define ACE_PEER_ACCEPTOR_ADDR PEER_ADDR +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +template <class SVC_HANDLER> +class ACE_Creation_Strategy + // = TITLE + // Defines the interface for specifying a creation strategy for + // a SVC_HANDLER. + // + // = DESCRIPTION + // The default behavior is to make a new SVC_HANDLER. However, + // subclasses can override this strategy to perform SVC_HANDLER + // creation in any way that they like (such as creating subclass + // instances of SVC_HANDLER, using a singleton, dynamically + // linking the handler, etc.). +{ +public: + // = Initialization and termination methods. + + ACE_Creation_Strategy (ACE_Thread_Manager * = 0); + // Default constructor. + + int open (ACE_Thread_Manager * = 0); + // A <Thread_Manager> is useful when creating active objects. + + virtual ~ACE_Creation_Strategy (void); + + // = Factory method. + virtual SVC_HANDLER *make_svc_handler (void); + // Create a SVC_HANDLER with the appropriate creation strategy. The + // default behavior of this method is to make a new SVC_HANDLER, + // passing in the Thread_Manager (if any). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_Thread_Manager *thr_mgr_; +}; + +template <class SVC_HANDLER> +class ACE_Singleton_Strategy : public ACE_Creation_Strategy<SVC_HANDLER> + // = TITLE + // Defines the interface for specifying a creation strategy for + // a <SVC_HANDLER> that always returns the same <SVC_HANDLER> (i.e., + // it's a Singleton). + // + // = DESCRIPTION + // Note that this class takes over the ownership of the + // SVC_HANDLER passed into it as a parameter and it becomes + // responsible for deleting this object. +{ +public: + // = Initialization and termination methods. + ACE_Singleton_Strategy (SVC_HANDLER * = 0, + ACE_Thread_Manager * = 0); + int open (SVC_HANDLER *, + ACE_Thread_Manager * = 0); + ~ACE_Singleton_Strategy (void); + + // = Factory method. + virtual SVC_HANDLER *make_svc_handler (void); + // Create a Singleton SVC_HANDLER by always returning the same + // SVC_HANDLER. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + SVC_HANDLER *svc_handler_; + // Pointer to the Singleton svc_handler. +}; + +template <class SVC_HANDLER> +class ACE_DLL_Strategy : public ACE_Creation_Strategy<SVC_HANDLER> + // = TITLE + // Defines the interface for specifying a creation strategy for + // a SVC_HANDLER based on dynamic linking of the SVC_HANDLER. +{ +public: + // = Intialization and termination methods. + + ACE_DLL_Strategy (void); + // "Do-nothing" constructor. + + ACE_DLL_Strategy (const char svc_dll_info[], + ACE_Service_Config *, + ACE_Thread_Manager * = 0); + // Initialize the DLL strategy based upon the service's DLL + // information contained in the <svc_dll_info> string. + + int open (const char svc_dll_info[], + ACE_Service_Config *, + ACE_Thread_Manager * = 0); + // Initialize the DLL strategy based upon the service's DLL + // information contained in the <svc_dll_info> string. + + // = Factory method. + virtual SVC_HANDLER *make_svc_handler (void); + // Create a SVC_HANDLER by dynamically linking it from a DLL. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + typedef ACE_Creation_Strategy<SVC_HANDLER> inherited; + + char shared_library_[MAXPATHLEN]; + // Name of the shared library to dynamically link. + + char factory_function_[MAXPATHLEN]; + // Name of the factory function in the shared library to use to + // obtain a pointer to the new SVC_HANDLER. + + char svc_name[MAXNAMELEN]; + // Name of the service. + + ACE_Service_Config *svc_config_; + // Pointer to the Service_Configurator. +}; + +template <class SVC_HANDLER> +class ACE_Concurrency_Strategy + // = TITLE + // Defines the interface for specifying a concurrency strategy + // for a SVC_HANDLER. + // + // = DESCRIPTION + // Default behavior is to activate the SVC_HANDLER by calling + // its open() method (which allows the SVC_HANDLER to define its + // own concurrency strategy). However, subclasses can override + // this default strategy to do more sophisticated concurrency + // activations (such as creating the SVC_HANDLER as an active + // object via multi-threading or multi-processing). +{ +public: + // = Factory method. + virtual int activate_svc_handler (SVC_HANDLER *svc_handler, + void *arg = 0); + // Activate the <svc_handler> with an appropriate concurrency + // strategy. The default behavior of this method is to activate the + // SVC_HANDLER by calling its open() method (which allows the + // SVC_HANDLER to define its own concurrency strategy). + + virtual ~ACE_Concurrency_Strategy (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class SVC_HANDLER> +class ACE_Thread_Strategy : public ACE_Concurrency_Strategy<SVC_HANDLER> + // = TITLE + // Defines the interface for specifying a concurrency strategy + // for a <SVC_HANDLER> based on multithreading. + // + // = DESCRIPTION + // This class provides a strategy that manages the creation of + // threads to handle requests from clients concurrently. It + // behaves as a "thread factory", spawning threads "on-demand" + // to run the service specified by a user-supplied + // <SVC_HANDLER>. +{ +public: + // = Intialization and termination methods. + ACE_Thread_Strategy (void); + // "Do-nothing constructor" + + ACE_Thread_Strategy (ACE_Thread_Manager *tm, + long thr_flags, + int n_threads = 1); + // Initialize the strategy. + + virtual int open (ACE_Thread_Manager *tm, + long thr_flags, + int n_threads = 1); + // Initialize the strategy. + + ~ACE_Thread_Strategy (void); + + // = Factory method. + virtual int activate_svc_handler (SVC_HANDLER *svc_handler, + void *arg = 0); + // Activate the <svc_handler> with an appropriate concurrency + // strategy. This method activates the SVC_HANDLER by first calling + // its open() method and then calling its activate() method to turn + // it into an active object. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + typedef ACE_Concurrency_Strategy<SVC_HANDLER> inherited; + + ACE_Thread_Manager *thr_mgr_; + // Thread manager for this class (must be provided). + + long thr_flags_; + // Flags to pass into the SVC_HANDLER::activate() method. + + int n_threads_; + // Number of threads to spawn. +}; + +template <class SVC_HANDLER> +class ACE_Process_Strategy : public ACE_Concurrency_Strategy<SVC_HANDLER> + // = TITLE + // Defines the interface for specifying a concurrency strategy + // for a <SVC_HANDLER> based on multiprocessing. + // + // = DESCRIPTION + // This class provides a strategy that manages the creation of + // processes to handle requests from clients concurrently. It + // behaves as a "process factory", forking threads "on-demand" + // to run the service specified by a user-supplied + // <SVC_HANDLER>. +{ +public: + // = Intialization and termination methods. + ACE_Process_Strategy (void); + // "Do-nothing constructor" + + ACE_Process_Strategy (int n_processes = 1); + // Initialize the strategy. + + virtual int open (int n_processes = 1); + // Initialize the strategy. + + ~ACE_Process_Strategy (void); + + // = Factory method. + virtual int activate_svc_handler (SVC_HANDLER *svc_handler, + void *arg = 0); + // Activate the <svc_handler> with an appropriate concurrency + // strategy. This method activates the SVC_HANDLER by first forking + // and then calling the open() method of the SVC_HANDLER in the + // child. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + typedef ACE_Concurrency_Strategy<SVC_HANDLER> inherited; + + int n_processes_; + // Number of processes to spawn. +}; + +template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> +class ACE_Accept_Strategy + // = TITLE + // Defines the interface for specifying a passive connection + // acceptance strategy for a SVC_HANDLER. + // + // = DESCRIPTION + // This class provides a strategy that manages passive + // connection acceptance of a client. +{ +public: + // = Initialization and termination methods. + ACE_Accept_Strategy (void); + // Default constructor. + + ACE_Accept_Strategy (const ACE_PEER_ACCEPTOR_ADDR &local_addr, + int restart = 0); + // Initialize the <peer_acceptor_> with <local_addr>. + + virtual int open (const ACE_PEER_ACCEPTOR_ADDR &local_addr, + int restart = 0); + // Initialize the <peer_acceptor_> with <local_addr>. + + virtual ACE_HANDLE get_handle (void) const; + // Return the underlying ACE_HANDLE of the <peer_acceptor_>. + + virtual ACE_PEER_ACCEPTOR &acceptor (void) const; + // Return a reference to the <peer_acceptor_>. + + ~ACE_Accept_Strategy (void); + + // = Factory method. + virtual int accept_svc_handler (SVC_HANDLER *); + // The default behavior delegates to the <accept> method of the + // PEER_ACCEPTOR. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_PEER_ACCEPTOR peer_acceptor_; + // Factory that establishes connections passively. +}; + +template <class SVC_HANDLER> +class ACE_Scheduling_Strategy + // = TITLE + // Defines the interface for specifying how to suspend and + // resume a service . + // + // = DESCRIPTION + // This class provides a strategy that allows arbitrarily + // sophisticated service suspension and resumption. The default + // behavior is to do nothing... +{ +public: + // = Initialization and termination methods. + + ACE_Scheduling_Strategy (SVC_HANDLER * = 0); + // Constructor + + ~ACE_Scheduling_Strategy (void); + // Destructor + + // = Scheduling methods + + virtual int suspend (void); + // Suspend hook. + + virtual int resume (void); + // Resume hook. + + virtual void dump (void) const; + // Dump the state of the object. + +protected: + SVC_HANDLER *scheduler_; + // Points to the scheduler strategy object... + + int delete_scheduler_; + // Keeps track of whether we need to delete this or not... +}; + +template <class SVC_HANDLER> +class ACE_Schedule_All_Reactive_Strategy : public ACE_Scheduling_Strategy<SVC_HANDLER> + // = TITLE + // Defines the interface for specifying how to suspend and + // resume a single-threaded reactive service . + // + // = DESCRIPTION + // This class provides a strategy that suspends and resumes all + // the Event_Handlers in a Reactor in one fell swoop. +{ +public: + // = Initialization and termination methods. + ACE_Schedule_All_Reactive_Strategy (SVC_HANDLER * = 0); + // Constructor + + // = Scheduling methods + + virtual int suspend (void); + // Suspend hook. + + virtual int resume (void); + // Resume hook. + + virtual void dump (void) const; + // Dump the state of the object. +}; + +template <class SVC_HANDLER> +class ACE_Schedule_All_Threaded_Strategy : public ACE_Scheduling_Strategy<SVC_HANDLER> + // = TITLE + // Defines the interface for specifying how to suspend and + // resume a multithreaded service . + // + // = DESCRIPTION + // This class provides a strategy that suspends and resumes all + // the Event_Handlers controlled by a Thread_Manager in one fell swoop. +{ +public: + // = Initialization and termination methods. + ACE_Schedule_All_Threaded_Strategy (SVC_HANDLER * = 0); + // Constructor + + // = Scheduling methods + + virtual int suspend (void); + // Suspend hook. + + virtual int resume (void); + // Resume hook. + + virtual void dump (void) const; + // Dump the state of the object. +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Strategies.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Strategies.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_STRATEGIES_H */ diff --git a/ace/Strategies.i b/ace/Strategies.i new file mode 100644 index 00000000000..a8f84ba003e --- /dev/null +++ b/ace/Strategies.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Strategies.i diff --git a/ace/Stream.cpp b/ace/Stream.cpp new file mode 100644 index 00000000000..7b17d555b80 --- /dev/null +++ b/ace/Stream.cpp @@ -0,0 +1,512 @@ +// Stream.cpp +// $Id$ + +#if !defined (ACE_STREAM_C) +#define ACE_STREAM_C + +#define ACE_BUILD_DLL +//#include "ace/Module.h" +#include "ace/Stream.h" +#include "ace/Stream_Modules.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Stream.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Stream) + +// Give some idea of what the heck is going on in a stream! + +template <ACE_SYNCH_1> void +ACE_Stream<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::dump"); + ACE_DEBUG ((LM_DEBUG, "-------- module links --------\n")); + + for (ACE_Module<ACE_SYNCH_2> *mp = this->stream_head_; ; mp = mp->next ()) + { + ACE_DEBUG ((LM_DEBUG, "module name = %s\n", mp->name ())); + if (mp == this->stream_tail_) + break; + } + + ACE_DEBUG ((LM_DEBUG, "-------- writer links --------\n")); + + ACE_Task<ACE_SYNCH_2> *qp; + + for (qp = this->stream_head_->writer (); ; qp = qp->next ()) + { + ACE_DEBUG ((LM_DEBUG, "writer queue name = %s\n", qp->name ())); + qp->dump (); + ACE_DEBUG ((LM_DEBUG, "-------\n")); + if (qp == this->stream_tail_->writer () + || (this->linked_us_ && qp == this->linked_us_->stream_head_->reader ())) + break; + } + + ACE_DEBUG ((LM_DEBUG, "-------- reader links --------\n")); + for (qp = this->stream_tail_->reader (); ; qp = qp->next ()) + { + ACE_DEBUG ((LM_DEBUG, "reader queue name = %s\n", qp->name ())); + qp->dump (); + ACE_DEBUG ((LM_DEBUG, "-------\n")); + if (qp == this->stream_head_->reader () + || (this->linked_us_ && qp == this->linked_us_->stream_head_->writer ())) + break; + } +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::push (ACE_Module<ACE_SYNCH_2> *new_top) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::push"); + if (this->push_module (new_top, + this->stream_head_->next (), + this->stream_head_) == -1) + return -1; + else + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Iterator<ACE_SYNCH_2>::advance (void) +{ + ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_2>::advance"); + this->next_ = this->next_->next (); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::put (ACE_Message_Block *mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::put"); + return this->stream_head_->writer ()->put (mb, tv); +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::get (ACE_Message_Block *&mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::get"); + return this->stream_head_->reader ()->getq (mb, tv); +} + +// Return the "top" ACE_Module in a ACE_Stream, skipping over the +// stream_head. + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::top (ACE_Module<ACE_SYNCH_2> *&m) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::top"); + if (this->stream_head_->next () == this->stream_tail_) + return -1; + else + { + m = this->stream_head_->next (); + return 0; + } +} + +// Remove the "top" ACE_Module in a ACE_Stream, skipping over the +// stream_head. + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::pop (u_long flags) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::pop"); + if (this->stream_head_->next () == this->stream_tail_) + return -1; + else + { + // Skip over the ACE_Stream head. + ACE_Module<ACE_SYNCH_2> *top = this->stream_head_->next (); + ACE_Module<ACE_SYNCH_2> *new_top = top->next (); + + this->stream_head_->next (new_top); + + // Close the top ACE_Module. + + top->close (flags); + + this->stream_head_->writer ()->next (new_top->writer ()); + new_top->reader ()->next (this->stream_head_->reader ()); + + return 0; + } +} + +// Remove a named ACE_Module from an arbitrary place in the +// ACE_Stream. + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::remove (const char *name, u_long flags) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::remove"); + ACE_Module<ACE_SYNCH_2> *prev = 0; + + for (ACE_Module<ACE_SYNCH_2> *mod = this->stream_head_; mod != 0; mod = mod->next ()) + if (ACE_OS::strcmp (mod->name (), name) == 0) + { + if (prev == 0) // Deleting ACE_Stream Head + this->stream_head_->link (mod->next ()); + else + prev->link (mod->next ()); + + mod->close (flags); + return 0; + } + else + prev = mod; + + return -1; +} + +template <ACE_SYNCH_1> ACE_Module<ACE_SYNCH_2> * +ACE_Stream<ACE_SYNCH_2>::find (const char *name) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::find"); + for (ACE_Module<ACE_SYNCH_2> *mod = this->stream_head_; + mod != 0; + mod = mod->next ()) + if (ACE_OS::strcmp (mod->name (), name) == 0) + return mod; + + return 0; +} + +// Actually push a module onto the stack... + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::push_module (ACE_Module<ACE_SYNCH_2> *new_top, + ACE_Module<ACE_SYNCH_2> *current_top, + ACE_Module<ACE_SYNCH_2> *head) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::push_module"); + ACE_Task<ACE_SYNCH_2> *nt_reader = new_top->reader (); + ACE_Task<ACE_SYNCH_2> *nt_writer = new_top->writer (); + ACE_Task<ACE_SYNCH_2> *ct_reader = 0; + ACE_Task<ACE_SYNCH_2> *ct_writer = 0; + + if (current_top) + { + ct_reader = current_top->reader (); + ct_writer = current_top->writer (); + ct_reader->next (nt_reader); + } + + nt_writer->next (ct_writer); + + if (head) + { + if (head != new_top) + head->link (new_top); + } + else + nt_reader->next (0); + + new_top->next (current_top); + + if (nt_reader->open (new_top->arg ()) == -1) + return -1; + + if (nt_writer->open (new_top->arg ()) == -1) + return -1; + return 0; +} + +#if 0 +int +ACE_Stream<ACE_SYNCH_2>::open (void *a, + ACE_Multiplexor &muxer, + ACE_Module<ACE_SYNCH_2> *head) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::open"); + this->stream_head_ = head == 0 + ? new ACE_Module<ACE_SYNCH_2> ("ACE_Stream_Head", + new ACE_Stream_Head<ACE_SYNCH_2>, + new ACE_Stream_Head<ACE_SYNCH_2>, a) : head; + this->stream_tail_ = 0; + return muxer.link_from_below (this->stream_head_); +} +#endif + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::open (void *a, + ACE_Module<ACE_SYNCH_2> *head, + ACE_Module<ACE_SYNCH_2> *tail) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::open"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + ACE_Task<ACE_SYNCH_2> *h1, *h2; + ACE_Task<ACE_SYNCH_2> *t1, *t2; + + if (head == 0) + { + h1 = new ACE_Stream_Head<ACE_SYNCH_2>; + h2 = new ACE_Stream_Head<ACE_SYNCH_2>; + head = new ACE_Module<ACE_SYNCH_2> ("ACE_Stream_Head", h1, h2, a); + } + + if (tail == 0) + { + t1 = new ACE_Stream_Tail<ACE_SYNCH_2>; + t2 = new ACE_Stream_Tail<ACE_SYNCH_2>; + tail = new ACE_Module<ACE_SYNCH_2> ("ACE_Stream_Tail", + t1, t2, a); + } + + // Make sure *all* the allocation succeeded! + if (h1 == 0 || h2 == 0 || head == 0 + || t1 == 0 || t2 == 0 || tail == 0) + { + delete h1; + delete h2; + delete t1; + delete t2; + // Note that we can't call delete on these, we must call close! + head->close (); + tail->close (); + errno = ENOMEM; + return -1; + } + + this->stream_head_ = head; + this->stream_tail_ = tail; + + if (this->push_module (this->stream_tail_) == -1) + return -1; + else if (this->push_module (this->stream_head_, + this->stream_tail_, + this->stream_head_) == -1) + return -1; + else + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::close (u_long flags) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::close"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + if (this->stream_head_ != 0 + && this->stream_tail_ != 0) + { + // Don't bother checking return value here. + this->unlink_i (); + + int result = 0; + + // Remove and cleanup all the intermediate modules. + + while (this->stream_head_->next () != this->stream_tail_) + { + if (this->pop (flags) == -1) + result = -1; + } + + // Clean up the head and tail of the stream. + if (this->stream_head_->close (flags) == -1) + result = -1; + if (this->stream_tail_->close (flags) == -1) + result = -1; + + this->stream_head_ = 0; + this->stream_tail_ = 0; + + // Tell all threads waiting on the close that we are done. + this->final_close_.broadcast (); + return result; + } + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::control (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd, + void *a) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::control"); + ACE_IO_Cntl_Msg ioc (cmd); + + // Create a data block that contains the user-supplied data. + ACE_Message_Block *db = + new ACE_Message_Block (sizeof (int), + ACE_Message_Block::MB_IOCTL, + 0, + (char *) a); + + // Create a control block that contains the control field and a + // pointer to the data block. + ACE_Message_Block *cb = + new ACE_Message_Block (sizeof ioc, + ACE_Message_Block::MB_IOCTL, + db, + (char *) &ioc); + + // Make sure all of the allocation succeeded before continuing. + if (db == 0 || cb == 0) + { + delete cb; + delete db; + errno = ENOMEM; + return -1; + } + + int result = 0; + + if (this->stream_head_->writer ()->put (cb) == -1) + result = -1; + else if (this->stream_head_->reader ()->getq (cb) == -1) + result = -1; + else + result = ((ACE_IO_Cntl_Msg *) cb->rd_ptr ())->rval (); + + delete cb; // This also deletes db... + return result; +} + +// Link two streams together at their bottom-most Modules (i.e., the +// one just above the Stream tail). Note that all of this is premised +// on the fact that the Stream head and Stream tail are non-NULL... +// This must be called with locks held. + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::link_i (ACE_Stream<ACE_SYNCH_2> &us) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::link_i"); + this->linked_us_ = &us; + // Make sure the other side is also linked to us! + us.linked_us_ = this; + + ACE_Module<ACE_SYNCH_2> *my_tail = this->stream_head_; + + if (my_tail == 0) + return -1; + + // Locate the module just above our Stream tail. + while (my_tail->next () != this->stream_tail_) + my_tail = my_tail->next (); + + ACE_Module<ACE_SYNCH_2> *other_tail = us.stream_head_; + + if (other_tail == 0) + return -1; + + // Locate the module just above the other Stream's tail. + while (other_tail->next () != us.stream_tail_) + other_tail = other_tail->next (); + + // Reattach the pointers so that the two streams are linked! + my_tail->writer ()->next (other_tail->reader ()); + other_tail->writer ()->next (my_tail->reader ()); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::link (ACE_Stream<ACE_SYNCH_2> &us) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::link"); + + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + + return this->link_i (us); +} + +// Must be called with locks held... + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::unlink_i (void) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::unlink_i"); + + // Only try to unlink if we are in fact still linked! + + if (this->linked_us_ != 0) + { + ACE_Module<ACE_SYNCH_2> *my_tail = this->stream_head_; + + // Only relink if we still exist! + if (my_tail) + { + // Find the module that's just before our stream tail. + while (my_tail->next () != this->stream_tail_) + my_tail = my_tail->next (); + + // Restore the writer's next() link to our tail. + my_tail->writer ()->next (this->stream_tail_->writer ()); + } + + ACE_Module<ACE_SYNCH_2> *other_tail = + this->linked_us_->stream_head_; + + // Only fiddle with the other side if it in fact still remains. + if (other_tail != 0) + { + while (other_tail->next () != this->linked_us_->stream_tail_) + other_tail = other_tail->next (); + + other_tail->writer ()->next (this->linked_us_->stream_tail_->writer ()); + + } + + // Make sure the other side is also aware that it's been unlinked! + this->linked_us_->linked_us_ = 0; + + this->linked_us_ = 0; + return 0; + } + else + return -1; +} + +template <ACE_SYNCH_1> int +ACE_Stream<ACE_SYNCH_2>::unlink (void) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::unlink"); + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1); + return this->unlink_i (); +} + +template <ACE_SYNCH_1> ACE_INLINE +ACE_Stream<ACE_SYNCH_2>::ACE_Stream (void * a, + ACE_Module<ACE_SYNCH_2> *head, + ACE_Module<ACE_SYNCH_2> *tail) + : final_close_ (this->lock_), + linked_us_ (0) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::ACE_Stream"); + if (this->open (a, head, tail) == -1) + ACE_ERROR ((LM_ERROR, "ACE_Stream<ACE_SYNCH_2>::open (%s, %s)\n", + head->name (), tail->name ())); +} + +#if 0 +ACE_INLINE +ACE_Stream<ACE_SYNCH_2>::ACE_Stream (void *a, + ACE_Multiplexor &muxer, + ACE_Module<ACE_SYNCH_2> *head) + : final_close_ (this->lock_), + linked_us_ (0) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::ACE_Stream"); + if (this->open (a, muxer, head) == -1) + ACE_ERROR ((LM_ERROR, "ACE_Stream<ACE_SYNCH_2>::open (%s, %s)\n", + head->name ())); +} +#endif + +template <ACE_SYNCH_1> ACE_INLINE +ACE_Stream<ACE_SYNCH_2>::~ACE_Stream (void) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::~ACE_Stream"); + if (this->stream_head_ != 0) + this->close (); +} + +template <ACE_SYNCH_1> ACE_INLINE +ACE_Stream_Iterator<ACE_SYNCH_2>::ACE_Stream_Iterator (const ACE_Stream<ACE_SYNCH_2> &sr) + : next_ (sr.stream_head_) +{ + ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_2>::ACE_Stream_Iterator"); +} + +#endif /* ACE_STREAM_C */ diff --git a/ace/Stream.h b/ace/Stream.h new file mode 100644 index 00000000000..0eeac5fc837 --- /dev/null +++ b/ace/Stream.h @@ -0,0 +1,185 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Stream.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_STREAM_H) +#define ACE_STREAM_H + +//#include "ace/Multiplexor.h" + +#include "ace/ACE.h" +#include "ace/IO_Cntl_Msg.h" +#include "ace/Message_Block.h" +#include "ace/Time_Value.h" +#include "ace/Module.h" + +// Forward decls. +template<ACE_SYNCH_1> class ACE_Stream_Iterator; +//template<ACE_SYNCH_1> class ACE_Module; + +template <ACE_SYNCH_1> +class ACE_Stream + // = TITLE + // This class is the primary abstraction for the ASX framework. + // It is moduled after System V Stream. + // + // = DESCRIPTION + // A Stream consists of a stack of <ACE_Modules>, each of which + // contains two <ACE_Tasks>. +{ +friend class ACE_Stream_Iterator<ACE_SYNCH_2>; +public: + enum + { + M_DELETE = 1 + // Indicates that close() deletes the Tasks. Don't change this + // value without updating the same enum in class ACE_Module... + }; + + // = Initializatation and termination methods. + ACE_Stream (void *arg = 0, + ACE_Module<ACE_SYNCH_2> *head = 0, + ACE_Module<ACE_SYNCH_2> *tail = 0); + // Create a Stream consisting of <head> and <tail> as the Stream + // head and Stream tail, respectively. If these are 0 then the + // <ACE_Stream_Head> and <ACE_Stream_Tail> are used, respectively. + // <arg> is the value past in to the open() methods of the tasks. + + int open (void *arg, + ACE_Module<ACE_SYNCH_2> *head = 0, + ACE_Module<ACE_SYNCH_2> *tail = 0); + // Create a Stream consisting of <head> and <tail> as the Stream + // head and Stream tail, respectively. If these are 0 then the + // <ACE_Stream_Head> and <ACE_Stream_Tail> are used, respectively. + // <arg> is the value past in to the open() methods of the tasks. + + int close (u_long flags = M_DELETE); + // Close down the stream and release all the resources. + + ~ACE_Stream (void); + // Close down the stream and release all the resources. + + // = ACE_Stream plumbing operations + + int push (ACE_Module<ACE_SYNCH_2> *mod); + // Add a new module <mod> right below the Stream head. + + int pop (u_long flags = M_DELETE); + // Remove the <mod> right below the Stream head and close it down. + + int top (ACE_Module<ACE_SYNCH_2> *&mod); + // Return the top module on the stream (right below the stream + // head). + + int remove (const char *mod, u_long flags = M_DELETE); + // Remove the named module <mod> from the stream. This bypasses the + // strict LIFO ordering of push() and pop(). + + ACE_Module<ACE_SYNCH_2> *head (void); + // Return current stream head. + + ACE_Module<ACE_SYNCH_2> *tail (void); + // Return current stream tail. + + ACE_Module<ACE_SYNCH_2> *find (const char *mod); + // Find a particular ACE_Module. + + int link (ACE_Stream<ACE_SYNCH_2> &); + // Create a pipe between two Streams. + + int unlink (void); + // Remove a pipe formed between two Streams. + + // = Blocking data transfer operations + int put (ACE_Message_Block *mb, ACE_Time_Value *timeout); + // Send the message <mb> down the stream, starting at the Module + // below the Stream head. Wait for upto <timeout> amount of time + // for the operation to complete (or block forever if <timeout> == + // 0). + + int get (ACE_Message_Block *&mb, ACE_Time_Value *timeout); + // Read the message <mb> that is stored in the the stream head. + // Wait for upto <timeout> amount of time for the operation to + // complete (or block forever if <timeout> == 0). + + int control (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd, void *args); + // Send control message down the stream. + + int wait (void); + // Synchronize with the final close of the stream. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int unlink_i (void); + // Actually perform the unlinking of two Streams (must be called + // with locks held). + + int link_i (ACE_Stream<ACE_SYNCH_2> &); + // Actually perform the linking of two Streams (must be called with + // locks held). + + int push_module (ACE_Module<ACE_SYNCH_2> *, + ACE_Module<ACE_SYNCH_2> * = 0, + ACE_Module<ACE_SYNCH_2> * = 0); + // Must a new module onto the Stream. + + ACE_Module<ACE_SYNCH_2> *stream_head_; + // Pointer to the head of the stream. + + ACE_Module<ACE_SYNCH_2> *stream_tail_; + // Pointer to the tail of the stream. + + ACE_Stream<ACE_SYNCH_2> *linked_us_; + // Pointer to an adjoining linked stream. + + // = Synchronization objects used for thread-safe streams. + ACE_SYNCH_MUTEX lock_; + // Protect the stream against race conditions. + + ACE_SYNCH_CONDITION final_close_; + // Use to tell all threads waiting on the close that we are done. +}; + +template <ACE_SYNCH_1> +class ACE_Stream_Iterator +{ +public: + ACE_Stream_Iterator (const ACE_Stream<ACE_SYNCH_2> &sr); + int next (const ACE_Module<ACE_SYNCH_2> *&mo); + int advance (void); + +private: + ACE_Module<ACE_SYNCH_2> *next_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Stream.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Stream.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Stream.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_STREAM_H */ diff --git a/ace/Stream.i b/ace/Stream.i new file mode 100644 index 00000000000..2a0fcc438a2 --- /dev/null +++ b/ace/Stream.i @@ -0,0 +1,35 @@ +/* -*- C++ -*- */ +// $Id$ + +// Stream.i + +#include "ace/Log_Msg.h" + +template <ACE_SYNCH_1> ACE_INLINE ACE_Module<ACE_SYNCH_2> * +ACE_Stream<ACE_SYNCH_2>::head (void) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::head"); + return this->stream_head_; +} + +template <ACE_SYNCH_1> ACE_INLINE ACE_Module<ACE_SYNCH_2> * +ACE_Stream<ACE_SYNCH_2>::tail (void) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::tail"); + return this->stream_tail_; +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Stream<ACE_SYNCH_2>::wait (void) +{ + ACE_TRACE ("ACE_Stream<ACE_SYNCH_2>::wait"); + return this->final_close_.wait (); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Stream_Iterator<ACE_SYNCH_2>::next (const ACE_Module<ACE_SYNCH_2> *&mod) +{ + ACE_TRACE ("ACE_Stream_Iterator<ACE_SYNCH_2>::next"); + mod = this->next_; + return this->next_ != 0; +} diff --git a/ace/Stream_Modules.cpp b/ace/Stream_Modules.cpp new file mode 100644 index 00000000000..53428b31305 --- /dev/null +++ b/ace/Stream_Modules.cpp @@ -0,0 +1,330 @@ +// Stream_Modules.cpp +// $Id$ + +#if !defined (ACE_STREAM_MODULES_C) +#define ACE_STREAM_MODULES_C + +#define ACE_BUILD_DLL +#include "ace/Stream_Modules.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Stream_Modules.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Head) + +template <ACE_SYNCH_1> void +ACE_Stream_Head<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::dump"); +} + +/* ACE_Module that act as the head and tail of a Stream. */ + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::open (void *) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::open"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::close (u_long) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::close"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::svc (void) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::svc"); + return -1; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::control (ACE_Message_Block *mb) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::control"); + ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr (); + ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd; + + switch (cmd = ioc->cmd ()) + { + case ACE_IO_Cntl_Msg::SET_LWM: + case ACE_IO_Cntl_Msg::SET_HWM: + this->water_marks (cmd, *(size_t *) mb->cont ()->rd_ptr ()); + ioc->rval (0); + break; + default: + return 0; + } + return ioc->rval (); +} + +/* Performs canonical flushing at the ACE_Stream Head */ + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::canonical_flush (ACE_Message_Block *mb) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::canonical_flush"); + char *cp = mb->rd_ptr (); + + if (*cp & ACE_Task_Flags::ACE_FLUSHR) + { + this->flush (ACE_Task_Flags::ACE_FLUSHALL); + *cp &= ~ACE_Task_Flags::ACE_FLUSHR; + } + if (*cp & ACE_Task_Flags::ACE_FLUSHW) + return this->reply (mb); + else + delete mb; + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::put (ACE_Message_Block *mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::put"); + int res = 0; + + if (mb->msg_type () == ACE_Message_Block::MB_IOCTL + && (res = this->control (mb)) == -1) + return res; + + if (this->is_writer ()) + { + return this->put_next (mb, tv); + } + else /* this->is_reader () */ + { + switch (mb->msg_type ()) + { + case ACE_Message_Block::MB_FLUSH: + return this->canonical_flush (mb); + default: + break; + } + + return this->putq (mb, tv); + } +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::init"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::info (char **strp, size_t length) const +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::info"); + const char *name = this->name (); + + if (*strp == 0 && (*strp = ACE_OS::strdup (name)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, name, length); + return ACE_OS::strlen (name); +} + +template <ACE_SYNCH_1> int +ACE_Stream_Head<ACE_SYNCH_2>::fini (void) +{ + ACE_TRACE ("ACE_Stream_Head<ACE_SYNCH_2>::fini"); + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Stream_Tail) + +template <ACE_SYNCH_1> void +ACE_Stream_Tail<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::dump"); +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::open (void *) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::open"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::close (u_long) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::close"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::svc (void) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::svc"); + return -1; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::control (ACE_Message_Block *mb) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::control"); + ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr (); + ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd; + + switch (cmd = ioc->cmd ()) + { + case ACE_IO_Cntl_Msg::SET_LWM: + case ACE_IO_Cntl_Msg::SET_HWM: + { + size_t size = *(size_t *) mb->cont ()->rd_ptr (); + + this->water_marks (cmd, size); + this->sibling ()->water_marks (cmd, size); + ioc->rval (0); + break; + } + default: + mb->msg_type (ACE_Message_Block::MB_IOCNAK); + } + return this->reply (mb); +} + +/* Perform flush algorithm as though we were the driver */ + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::canonical_flush (ACE_Message_Block *mb) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::canonical_flush"); + char *cp = mb->rd_ptr (); + + if (*cp & ACE_Task_Flags::ACE_FLUSHW) + { + this->flush (ACE_Task_Flags::ACE_FLUSHALL); + *cp &= ~ACE_Task_Flags::ACE_FLUSHW; + } + if (*cp & ACE_Task_Flags::ACE_FLUSHR) + { + this->sibling ()->flush (ACE_Task_Flags::ACE_FLUSHALL); + return this->reply (mb); + } + else + delete mb; + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::put (ACE_Message_Block *mb, ACE_Time_Value * + +) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::put"); + if (this->is_writer ()) + { + switch (mb->msg_type ()) + { + case ACE_Message_Block::MB_IOCTL: + return this->control (mb); + /* NOTREACHED */ + default: + delete mb; + } + } + + return -1; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::init"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::info (char **strp, size_t length) const +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::info"); + const char *name = this->name (); + + if (*strp == 0 && (*strp = ACE_OS::strdup (name)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, name, length); + return ACE_OS::strlen (name); +} + +template <ACE_SYNCH_1> int +ACE_Stream_Tail<ACE_SYNCH_2>::fini (void) +{ + ACE_TRACE ("ACE_Stream_Tail<ACE_SYNCH_2>::fini"); + return 0; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Thru_Task) + +template <ACE_SYNCH_1> void +ACE_Thru_Task<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::dump"); +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::open (void *) +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::open"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::close (u_long) +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::close"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::svc (void) +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::svc"); + return -1; +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::put (ACE_Message_Block *msg, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::put"); + return this->put_next (msg, tv); +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::init"); + return 0; +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::info (char **strp, + size_t length) const +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::info"); + const char *name = this->name (); + + if (*strp == 0 && (*strp = ACE_OS::strdup (name)) == 0) + return -1; + else + ACE_OS::strncpy (*strp, name, length); + return ACE_OS::strlen (name); +} + +template <ACE_SYNCH_1> int +ACE_Thru_Task<ACE_SYNCH_2>::fini (void) +{ + ACE_TRACE ("ACE_Thru_Task<ACE_SYNCH_2>::fini"); + return 0; +} + +#endif /* ACE_STREAM_MODULES_C */ diff --git a/ace/Stream_Modules.h b/ace/Stream_Modules.h new file mode 100644 index 00000000000..71db2247af5 --- /dev/null +++ b/ace/Stream_Modules.h @@ -0,0 +1,118 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Stream_Modules.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_STREAM_MODULES) +#define ACE_STREAM_MODULES + +#include "ace/Task.h" + +template <ACE_SYNCH_1> +class ACE_Stream_Head : public ACE_Task<ACE_SYNCH_2> + // = TITLE + // Standard module that acts as the head of a ustream. +{ +public: + // = ACE_Task hooks + virtual int open (void *a = 0); + virtual int close (u_long flags = 0); + virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0); + virtual int svc (void); + + // = Dynamic linking hooks + virtual int init (int argc, char *argv[]); + virtual int info (char **info_string, size_t length) const; + virtual int fini (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int control (ACE_Message_Block *); + int canonical_flush (ACE_Message_Block *); + // Performs canonical flushing at the ACE_Stream Head. +}; + +template <ACE_SYNCH_1> +class ACE_Stream_Tail : public ACE_Task<ACE_SYNCH_2> + // = TITLE + // Standard module that acts as the head of a ustream. +{ +public: + // = ACE_Task hooks + virtual int open (void *a = 0); + virtual int close (u_long flags = 0); + virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0); + virtual int svc (void); + + // = Dynamic linking hooks + virtual int init (int argc, char *argv[]); + virtual int info (char **info_string, size_t length) const; + virtual int fini (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int control (ACE_Message_Block *); + int canonical_flush (ACE_Message_Block *); + // Performs canonical flushing at the ACE_Stream tail. +}; + +template <ACE_SYNCH_1> +class ACE_Thru_Task : public ACE_Task<ACE_SYNCH_2> + // = TITLE + // Standard module that acts as a "no op", simply passing on all + // data to its adjacent neighbor. +{ +public: + // = ACE_Task hooks + virtual int open (void *a = 0); + virtual int close (u_long flags = 0); + virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0); + virtual int svc (void); + + // = Dynamic linking hooks + virtual int init (int argc, char *argv[]); + virtual int info (char **info_string, size_t length) const; + virtual int fini (void); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Stream_Modules.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Stream_Modules.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Stream_Modules.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_STREAM_MODULES */ diff --git a/ace/Stream_Modules.i b/ace/Stream_Modules.i new file mode 100644 index 00000000000..da761143bd8 --- /dev/null +++ b/ace/Stream_Modules.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Stream_Modules.i diff --git a/ace/Svc_Conf.h b/ace/Svc_Conf.h new file mode 100644 index 00000000000..a777b1ef880 --- /dev/null +++ b/ace/Svc_Conf.h @@ -0,0 +1,81 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Svc_Conf.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SVC_CONF_H) +#define ACE_SVC_CONF_H + +// Globally visible macros, type decls, and extern var decls for +// Service Configurator utility. + +#include "ace/Obstack.h" +#include "ace/Service_Config.h" +#include "ace/Parse_Node.h" + +#if defined (DEBUGGING) +#if defined (YY_DECL) +#undef YY_DECL +#endif +#define YY_DECL extern "C" char *ace_yylex (void) +#else +#define YY_DECL extern "C" int ace_yylex (void) +#endif /* DEBUGGING */ + +void ace_yyrestart (FILE *); +// Restart input file parsing + +int ace_yyparse (void); +// Performs the parsing + +YY_DECL; +// Performs the lexical analysis + +extern FILE *ace_yyin; +// Name of input stream + +void ace_yyerror (char *); +// Error handling routine required by YACC or BISON + +extern int ace_yylineno; +// Keeps track of the current line number for error-handling routine + +extern int ace_yyerrno; +// Keeps track of the number of errors encountered so far + +extern char *ace_yytext; +// Holds the lexeme for the current token + +extern int ace_yyleng; +// Holds the length of the lexeme for the current token + +extern ACE_Obstack *ace_obstack; +// Efficient memory allocation technique + +ACE_Service_Type *ace_create_service_type (const char *, int, const void *, unsigned int); +// Factory that creates a new ACE_Service_Type. + +typedef union +{ + int type_; + ACE_Location_Node *location_node_; + ACE_Parse_Node *parse_node_; + ACE_Static_Node *ACE_Static_Node_; + ACE_Service_Record *svc_record_; + char *ident_; +} YYSTYPE; +extern YYSTYPE ace_yylval; +#endif /* ACE_SVC_CONF_H */ + diff --git a/ace/Svc_Conf.l b/ace/Svc_Conf.l new file mode 100644 index 00000000000..029869e29c1 --- /dev/null +++ b/ace/Svc_Conf.l @@ -0,0 +1,77 @@ +%{ +// Sample lexical analysis for regular expression subset. Must be +// compiled with FLEX and an ANSI C++ compiler. + +// Lexical tokens values defined by YACC. +#include "ace/Svc_Conf.h" +#include "ace/Svc_Conf_Tokens.h" + +// Keeps track of the current line for debugging output. +int yylineno = 1; + +// Keeps track of the number of errors encountered so far. +int yyerrno = 0; + +#define token(x) x +%} + +%s PARAMETERS +%s NORMAL + +letter [a-zA-Z_] +letter_or_digit [a-zA-Z_0-9] +digit [0-9] +ident {letter}{letter_or_digit}* +pathname ([A-Za-z]:)?[a-zA-Z_0-9/\.\\-]+ +symbol [ -~] +string \"{symbol}+\" +white_space [ \t] +newline \n +other . + +%% + +^#{other}*$ ; /* EMPTY */ +dynamic { return token (ACE_DYNAMIC); } +static { return token (ACE_STATIC); } +suspend { return token (ACE_SUSPEND); } +resume { return token (ACE_RESUME); } +remove { return token (ACE_REMOVE); } +stream { return token (ACE_USTREAM); } +Module { return token (ACE_MODULE_T); } +Service_Object { return token (ACE_SVC_OBJ_T); } +STREAM { return token (ACE_STREAM_T); } +active { return token (ACE_ACTIVE); } +inactive { return token (ACE_INACTIVE); } +":" { return token (ACE_COLON); } +"*" { return token (ACE_STAR); } +"(" { return token (ACE_LPAREN); } +")" { return token (ACE_RPAREN); } +"{" { return token (ACE_LBRACE); } +"}" { return token (ACE_RBRACE); } +{string} { // Eliminate the opening and closing double quotes + *strrchr (yytext, '"') = '\0'; + yyleng -= 1; + yylval.ident_ = ace_obstack->copy (yytext + 1, yyleng); + return token (ACE_STRING); } +{ident} { + yylval.ident_ = ace_obstack->copy (yytext, yyleng); + return token (ACE_IDENT); + } +{pathname} { + yylval.ident_ = ace_obstack->copy (yytext, yyleng); + return token (ACE_PATHNAME); + } +{white_space}+ ; /* EMPTY */ +{newline} { yylineno++; } +{other} { ACE_ERROR ((LM_ERROR, "unknown char = %d\n", *yytext)); } +<<EOF>> { YY_NEW_FILE; yyterminate(); } +%% +int +yywrap (void) +{ + ::fflush (yyin); + yytext[0] = '#'; + yyleng = 0; + return 1; +} diff --git a/ace/Svc_Conf.y b/ace/Svc_Conf.y new file mode 100644 index 00000000000..842fbf1ce7b --- /dev/null +++ b/ace/Svc_Conf.y @@ -0,0 +1,342 @@ +%{ +#define ACE_BUILD_DLL +#include "ace/ARGV.h" +#include "ace/Svc_Conf.h" +#include "ace/Module.h" +#include "ace/Stream.h" + +static ACE_Module_Type *get_module (ACE_Static_Node *str_rec, ACE_Static_Node *svc_type); +static ACE_Module_Type *get_module (ACE_Static_Node *str_rec, const char *svc_name); + +#define YYDEBUG_LEXER_TEXT (yytext[yyleng] = '\0', yytext) +// Force the pretty debugging code to compile. +#define YYDEBUG 1 + +// Efficient memory allocation technique. +ACE_Obstack *ace_obstack; + +%} +%token ACE_DYNAMIC ACE_STATIC ACE_SUSPEND ACE_RESUME ACE_REMOVE ACE_USTREAM +%token ACE_MODULE_T ACE_STREAM_T ACE_SVC_OBJ_T ACE_ACTIVE ACE_INACTIVE +%token ACE_PATHNAME ACE_IDENT ACE_STRING +%token ACE_LPAREN ACE_RPAREN ACE_LBRACE ACE_RBRACE ACE_STAR ACE_COLON + +%start svc_config_entries + +%type <ident_> ACE_IDENT ACE_STRING ACE_PATHNAME parameters_opt +%type <type_> type status +%type <parse_node_> dynamic static suspend resume remove module_list stream +%type <parse_node_> stream_modules module svc_config_entry +%type <ACE_Static_Node_> stream_ops +%type <svc_record_> svc_location +%type <location_node_> svc_initializer + +%% + +svc_config_entries + : svc_config_entries svc_config_entry + { + $2->apply (); delete $2; ace_obstack->release (); + } + | svc_config_entries error + { + ace_obstack->release (); + } + | /* EMPTY */ + ; + +svc_config_entry + : dynamic + | static + | suspend + | resume + | remove + | stream + ; + +dynamic + : ACE_DYNAMIC svc_location parameters_opt + { + $$ = new ACE_Dynamic_Node ($2, $3); + } + ; + +static + : ACE_STATIC ACE_IDENT parameters_opt + { + $$ = new ACE_Static_Node ($2, $3); + } + ; + +suspend + : ACE_SUSPEND ACE_IDENT + { + $$ = new ACE_Suspend_Node ($2); + } + ; + +resume + : ACE_RESUME ACE_IDENT + { + $$ = new ACE_Resume_Node ($2); + } + ; + +remove + : ACE_REMOVE ACE_IDENT + { + $$ = new ACE_Remove_Node ($2); + } + ; + +stream + : ACE_USTREAM stream_ops stream_modules + { + $$ = new ACE_Stream_Node ($2, $3); + } + | ACE_USTREAM ACE_IDENT { $<ACE_Static_Node_>$ = new ACE_Static_Node ($2); } stream_modules + { + $$ = new ACE_Dummy_Node ($<ACE_Static_Node_>3, $4); + } + ; + +stream_ops + : dynamic + { + } + | static + { + } + ; + +stream_modules + : ACE_LBRACE + { + // Initialize left context... + $<ACE_Static_Node_>$ = $<ACE_Static_Node_>0; + } + module_list ACE_RBRACE + { + $$ = $3; + } + | /* EMPTY */ { $$ = 0; } + ; + +module_list + : module_list module { $2->link ($1); $$ = $2; } + | /* EMPTY */ { $$ = 0; } + ; + +module + : dynamic + { + ACE_ARGV args ($<ACE_Static_Node_>1->parameters ()); + ACE_Module_Type *mt = get_module ($<ACE_Static_Node_>-1, $<ACE_Static_Node_>1); + + if (::strcmp ($<ACE_Static_Node_>1->name (), + ((MT_Module *) mt->object ())->name ()) != 0) + ACE_ERROR ((LM_ERROR, "warning, service name %s is different from Module name %s\n", + $<ACE_Static_Node_>1->name (), ((MT_Module *) mt->object ())->name ())); + + if (mt->init (args.argc (), args.argv ()) == -1 + || ((ACE_Stream_Type *) ($<ACE_Static_Node_>-1)->record ()->type ())->push (mt) == -1) + { + ACE_ERROR ((LM_ERROR, "dynamic initialization failed for Module %s\n", + $<ACE_Static_Node_>1->name ())); + yyerrno++; + } + } + | static + { + ACE_Module_Type *mt = get_module ($<ACE_Static_Node_>-1, $<ACE_Static_Node_>1->name ()); + if (::strcmp ($<ACE_Static_Node_>1->name (), + ((MT_Module *) mt->object ())->name ()) != 0) + ACE_ERROR ((LM_ERROR, "warning, service name %s is different from Module name %s\n", + $<ACE_Static_Node_>1->name (), ((MT_Module *) mt->object ())->name ())); + if (((ACE_Stream_Type *) ($<ACE_Static_Node_>-1)->record ()->type ())->push (mt) == -1) + yyerrno++; + } + | suspend + { + ACE_Module_Type *mt = get_module ($<ACE_Static_Node_>-1, $<ACE_Static_Node_>1->name ()); + if (mt != 0) + mt->suspend (); + } + | resume + { + ACE_Module_Type *mt = get_module ($<ACE_Static_Node_>-1, $<ACE_Static_Node_>1->name ()); + if (mt != 0) + mt->resume (); + } + | remove + { + ACE_Module_Type *mt = get_module ($<ACE_Static_Node_>-1, $<ACE_Static_Node_>1->name ()); + if (mt != 0 + && ((ACE_Stream_Type *) ($<ACE_Static_Node_>-1)->record ()->type ())->remove (mt) == -1) + { + ACE_ERROR ((LM_ERROR, "cannot remove Module_Type %s from STREAM_Type %s\n", + $<ACE_Static_Node_>1->name (), ($<ACE_Static_Node_>-1)->name ())); + yyerrno++; + } + } + ; + +svc_location + : ACE_IDENT type svc_initializer status + { + unsigned int flags + = ACE_Service_Type::DELETE_THIS | ($3->dispose () == 0 ? 0 : ACE_Service_Type::DELETE_OBJ); + ACE_Service_Type *stp = ace_create_service_type ($1, $2, $3->symbol (), flags); + $$ = new ACE_Service_Record ($1, stp, $3->handle (), $4); + } + ; + +status + : ACE_ACTIVE + { + $$ = 1; + } + | ACE_INACTIVE + { + $$ = 0; + } + | /* EMPTY */ + { + $$ = 1; + } + ; + +svc_initializer + : ACE_PATHNAME ACE_COLON ACE_IDENT + { + $$ = new ACE_Object_Node ($1, $3); + } + | ACE_PATHNAME ACE_COLON ACE_IDENT ACE_LPAREN ACE_RPAREN + { + $$ = new ACE_Function_Node ($1, $3); + } + ; + +type + : ACE_MODULE_T ACE_STAR + { + $$ = ACE_MODULE_T; + } + | ACE_SVC_OBJ_T ACE_STAR + { + $$ = ACE_SVC_OBJ_T; + } + | ACE_STREAM_T ACE_STAR + { + $$ = ACE_STREAM_T; + } + ; + +parameters_opt + : ACE_STRING + | /* EMPTY */ { $$ = 0; } + ; + +%% +// Prints the error string to standard output. Cleans up the error +// messages. + +void +yyerror (char *s) +{ + ACE_ERROR ((LM_ERROR, "[error %d] on line %d: %s\n", + ++yyerrno, yylineno, s)); +} + +// Note that SRC_REC represents left context, which is the STREAM * +// record. + +static ACE_Module_Type * +get_module (ACE_Static_Node *str_rec, const char *svc_name) +{ + const ACE_Service_Record *sr = str_rec->record (); + const ACE_Service_Type *type = sr->type (); + ACE_Stream_Type *st = sr == 0 ? 0 : (ACE_Stream_Type *) type; + ACE_Module_Type *mt = st == 0 ? 0 : st->find (svc_name); + + if (sr == 0 || st == 0 || mt == 0) + { + ACE_ERROR ((LM_ERROR, "cannot locate Module_Type %s in STREAM_Type %s\n", + svc_name, str_rec->name ())); + yyerrno++; + } + return mt; +} + +static ACE_Module_Type * +get_module (ACE_Static_Node *str_rec, ACE_Static_Node *svc_type) +{ + const ACE_Service_Record *sr = str_rec->record (); + const ACE_Service_Type *type = sr->type (); + ACE_Stream_Type *st = sr == 0 ? 0 : (ACE_Stream_Type *) type; + const ACE_Service_Record *sv = svc_type->record (); + type = sv->type (); + ACE_Module_Type *mt = (ACE_Module_Type *) type; + + if (sr == 0 || st == 0 || mt == 0) + { + ACE_ERROR ((LM_ERROR, "cannot locate Module_Type %s or STREAM_Type %s\n", + svc_type->name (), str_rec->name ())); + yyerrno++; + } + return mt; +} + +ACE_Service_Type * +ace_create_service_type (const char *name, + int type, + const void *symbol, + unsigned int flags) +{ + ACE_Service_Type *stp = 0; + + // Note, the only place we need to put a case statement. This is + // also the place where we'd put the RTTI tests, if the compiler + // actually supported them! + + switch (type) + { + case ACE_SVC_OBJ_T: + stp = new ACE_Service_Object_Type ((ACE_Service_Object *) symbol, name, flags); + break; + case ACE_MODULE_T: + stp = new ACE_Module_Type ((MT_Module *) symbol, name, flags); + break; + case ACE_STREAM_T: + stp = new ACE_Stream_Type ((MT_Stream *) symbol, name, flags); + break; + default: + ACE_ERROR ((LM_ERROR, "unknown case\n")); + yyerrno++; + break; + } + return stp; +} + +#if defined (DEBUGGING) +// Current line number. +int yylineno = 1; + +// Name given on the command-line to envoke the program. +char *program_name; + +// Main driver program. + +int +main (int argc, char *argv[]) +{ + yyin = stdin; + ace_obstack = new ACE_Obstack; + + // Try to reopen any filename argument to use YYIN. + if (argc > 1 && (yyin = freopen (argv[1], "r", stdin)) == 0) + (void) ::fprintf (stderr, "usage: %s [file]\n", argv[0]), exit (1); + + return yyparse (); +} +#endif /* DEBUGGING */ diff --git a/ace/Svc_Conf_Tokens.h b/ace/Svc_Conf_Tokens.h new file mode 100644 index 00000000000..39e0e0ac4f0 --- /dev/null +++ b/ace/Svc_Conf_Tokens.h @@ -0,0 +1,23 @@ +/* -*- C++ -*- */ +// $Id$ + +#define ACE_DYNAMIC 257 +#define ACE_STATIC 258 +#define ACE_SUSPEND 259 +#define ACE_RESUME 260 +#define ACE_REMOVE 261 +#define ACE_USTREAM 262 +#define ACE_MODULE_T 263 +#define ACE_STREAM_T 264 +#define ACE_SVC_OBJ_T 265 +#define ACE_ACTIVE 266 +#define ACE_INACTIVE 267 +#define ACE_PATHNAME 268 +#define ACE_IDENT 269 +#define ACE_STRING 270 +#define ACE_LPAREN 271 +#define ACE_RPAREN 272 +#define ACE_LBRACE 273 +#define ACE_RBRACE 274 +#define ACE_STAR 275 +#define ACE_COLON 276 diff --git a/ace/Svc_Conf_l.cpp b/ace/Svc_Conf_l.cpp new file mode 100644 index 00000000000..9e7cd5ad934 --- /dev/null +++ b/ace/Svc_Conf_l.cpp @@ -0,0 +1,1504 @@ +/* A lexical scanner generated by flex */ +// $Id$ + + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <stdio.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#ifdef __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + + +#ifdef __TURBOC__ +#define YY_USE_CONST +#endif + + +#ifndef YY_USE_CONST +#ifndef const +#define const +#endif +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN ace_yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. + */ +#define YY_START ((ace_yy_start - 1) / 2) + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". Now included + * only for backward compatibility with previous versions of flex. + */ +#define YY_NEW_FILE ace_yyrestart( ace_yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct ace_yy_buffer_state *YY_BUFFER_STATE; + +extern int ace_yyleng; +extern FILE *ace_yyin, *ace_yyout; + +#ifdef __cplusplus +extern "C" { +#endif + extern int ace_yywrap YY_PROTO(( void )); +#ifdef __cplusplus + } +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * ace_yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the ace_yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define ace_yyless(n) \ + do \ + { \ + /* Undo effects of setting up ace_yytext. */ \ + *ace_yy_cp = ace_yy_hold_char; \ + ace_yy_c_buf_p = ace_yy_cp = ace_yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up ace_yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) ace_yyunput( c, ace_yytext_ptr ) + + +struct ace_yy_buffer_state + { + FILE *ace_yy_input_file; + + char *ace_yy_ch_buf; /* input buffer */ + char *ace_yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int ace_yy_buf_size; + + /* Number of characters read into ace_yy_ch_buf, not including EOB + * characters. + */ + int ace_yy_n_chars; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int ace_yy_is_interactive; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int ace_yy_fill_buffer; + + int ace_yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via ace_yyrestart()), so that the user can continue scanning by + * just pointing ace_yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE ace_yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER ace_yy_current_buffer + + +/* ace_yy_hold_char holds the character lost when ace_yytext is formed. */ +static char ace_yy_hold_char; + +static int ace_yy_n_chars; /* number of characters read into ace_yy_ch_buf */ + + +int ace_yyleng; + +/* Points to current character in buffer. */ +static char *ace_yy_c_buf_p = (char *) 0; +static int ace_yy_init = 1; /* whether we need to initialize */ +static int ace_yy_start = 0; /* start state number */ + +/* Flag which is used to allow ace_yywrap()'s to do buffer switches + * instead of setting up a fresh ace_yyin. A bit of a hack ... + */ +static int ace_yy_did_buffer_switch_on_eof; + +static void ace_yyunput YY_PROTO(( int c, char *buf_ptr )); +void ace_yyrestart YY_PROTO(( FILE *input_file )); +void ace_yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void ace_yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE ace_yy_create_buffer YY_PROTO(( FILE *file, int size )); +void ace_yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void ace_yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); + +static int ace_yy_start_stack_ptr = 0; +static int ace_yy_start_stack_depth = 0; +static int *ace_yy_start_stack = 0; +static void ace_yy_push_state YY_PROTO(( int new_state )); +static void ace_yy_pop_state YY_PROTO(( void )); +static int ace_yy_top_state YY_PROTO(( void )); + +static void *ace_yy_flex_alloc YY_PROTO(( unsigned int )); +static void *ace_yy_flex_realloc YY_PROTO(( void *, unsigned int )); +static void ace_yy_flex_free YY_PROTO(( void * )); + +#define ace_yy_new_buffer ace_yy_create_buffer + +#define INITIAL 0 +#define PARAMETERS 1 +#define NORMAL 2 +typedef unsigned char YY_CHAR; +typedef int ace_yy_state_type; +FILE *ace_yyin = (FILE *) 0, *ace_yyout = (FILE *) 0; +extern char *ace_yytext; +#define ace_yytext_ptr ace_yytext + +#ifndef ace_yytext_ptr +static void ace_yy_flex_strncpy YY_PROTO(( char *, const char *, int )); +#endif + +#ifdef __cplusplus +static int ace_yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif + +static ace_yy_state_type ace_yy_get_previous_state YY_PROTO(( void )); +static ace_yy_state_type ace_yy_try_NUL_trans YY_PROTO(( ace_yy_state_type current_state )); +static int ace_yy_get_next_buffer YY_PROTO(( void )); +static void ace_yy_fatal_error YY_PROTO(( const char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up ace_yytext. + */ +#define YY_DO_BEFORE_ACTION \ + ace_yytext_ptr = ace_yy_bp; \ + ace_yyleng = ace_yy_cp - ace_yy_bp; \ + ace_yy_hold_char = *ace_yy_cp; \ + *ace_yy_cp = '\0'; \ + ace_yy_c_buf_p = ace_yy_cp; + +#define YY_END_OF_BUFFER 26 +static const short int ace_yy_accept[103] = + { 0, + 0, 0, 0, 0, 0, 0, 26, 24, 22, 23, + 24, 15, 16, 14, 21, 13, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 17, 18, 24, 22, 0, + 21, 20, 0, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 0, 1, 19, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 8, 10, + 20, 11, 20, 20, 6, 5, 3, 7, 20, 20, + 2, 20, 4, 20, 12, 20, 20, 20, 20, 20, + + 9, 0 + } ; + +static const int ace_yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 6, 7, 5, 5, 5, 5, 8, + 9, 10, 5, 5, 11, 11, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 5, 5, + 5, 5, 5, 5, 14, 15, 15, 15, 16, 15, + 15, 15, 15, 15, 15, 15, 17, 15, 18, 15, + 15, 19, 20, 21, 15, 15, 15, 15, 15, 15, + 5, 11, 5, 5, 22, 5, 23, 24, 25, 26, + + 27, 15, 15, 15, 28, 29, 15, 30, 31, 32, + 33, 34, 15, 35, 36, 37, 38, 39, 15, 15, + 40, 15, 41, 5, 42, 5, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const int ace_yy_meta[43] = + { 0, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2 + } ; + +static const short int ace_yy_base[107] = + { 0, + 0, 111, 0, 107, 0, 90, 91, 313, 41, 313, + 0, 313, 313, 313, 0, 313, 33, 36, 37, 40, + 41, 44, 48, 49, 52, 313, 313, 82, 66, 76, + 0, 60, 0, 61, 64, 68, 75, 81, 82, 85, + 88, 89, 75, 313, 61, 93, 104, 96, 111, 115, + 116, 97, 121, 129, 133, 134, 137, 138, 142, 143, + 150, 151, 158, 161, 162, 166, 167, 172, 185, 180, + 173, 190, 193, 196, 197, 200, 201, 204, 209, 215, + 216, 220, 224, 227, 228, 231, 234, 235, 239, 240, + 243, 244, 247, 250, 256, 259, 262, 263, 267, 266, + + 271, 313, 302, 53, 304, 308 + } ; + +static const short int ace_yy_def[107] = + { 0, + 102, 1, 1, 1, 1, 1, 102, 102, 102, 102, + 103, 102, 102, 102, 104, 102, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 102, 102, 106, 102, 103, + 104, 105, 104, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 106, 102, 103, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + + 105, 0, 102, 102, 102, 102 + } ; + +static const short int ace_yy_nxt[356] = + { 0, + 8, 9, 10, 9, 8, 11, 8, 12, 13, 14, + 15, 15, 16, 17, 17, 17, 18, 17, 17, 19, + 17, 20, 21, 17, 17, 22, 17, 23, 17, 17, + 17, 17, 17, 17, 24, 25, 17, 17, 17, 17, + 26, 27, 29, 31, 29, 33, 31, 31, 33, 33, + 31, 31, 102, 33, 31, 31, 33, 35, 31, 31, + 33, 33, 31, 36, 33, 37, 45, 29, 34, 29, + 31, 31, 102, 102, 31, 40, 102, 44, 31, 39, + 102, 45, 47, 38, 44, 31, 46, 102, 41, 42, + 102, 31, 31, 102, 102, 31, 28, 102, 31, 31, + + 102, 102, 48, 31, 51, 102, 31, 31, 102, 102, + 54, 49, 50, 28, 31, 52, 102, 28, 102, 58, + 53, 31, 55, 102, 56, 31, 31, 102, 102, 63, + 57, 31, 102, 102, 59, 102, 102, 61, 60, 31, + 62, 102, 102, 31, 31, 102, 102, 31, 31, 102, + 102, 69, 31, 31, 102, 102, 102, 102, 64, 66, + 31, 31, 102, 102, 102, 65, 68, 67, 31, 70, + 102, 31, 31, 102, 102, 102, 31, 31, 102, 102, + 72, 71, 31, 31, 102, 102, 102, 73, 77, 76, + 31, 75, 102, 78, 102, 31, 74, 102, 79, 82, + + 31, 80, 102, 31, 81, 102, 31, 31, 102, 102, + 31, 31, 102, 102, 31, 102, 102, 83, 102, 31, + 84, 102, 85, 86, 87, 31, 31, 102, 102, 102, + 31, 88, 102, 102, 31, 89, 102, 31, 31, 102, + 102, 31, 90, 102, 31, 31, 102, 102, 91, 31, + 31, 102, 102, 31, 31, 102, 102, 31, 102, 102, + 31, 94, 102, 102, 93, 92, 31, 96, 102, 31, + 95, 102, 31, 31, 102, 102, 31, 31, 102, 102, + 102, 31, 97, 102, 102, 102, 102, 102, 102, 99, + 98, 100, 102, 102, 102, 102, 102, 102, 102, 102, + + 102, 102, 101, 30, 30, 30, 32, 32, 43, 43, + 43, 43, 7, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102 + } ; + +static const short int ace_yy_chk[356] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 9, 17, 9, 17, 18, 19, 18, 19, + 20, 21, 20, 21, 22, 104, 22, 19, 23, 24, + 23, 24, 25, 19, 25, 21, 45, 29, 18, 29, + 32, 34, 32, 34, 35, 24, 35, 43, 36, 23, + 36, 30, 35, 22, 28, 37, 34, 37, 25, 25, + 7, 38, 39, 38, 39, 40, 6, 40, 41, 42, + + 41, 42, 36, 46, 39, 46, 48, 52, 48, 52, + 41, 37, 38, 4, 47, 40, 47, 2, 0, 47, + 40, 49, 41, 49, 42, 50, 51, 50, 51, 52, + 46, 53, 0, 53, 48, 0, 0, 50, 49, 54, + 51, 54, 0, 55, 56, 55, 56, 57, 58, 57, + 58, 58, 59, 60, 59, 60, 0, 0, 53, 55, + 61, 62, 61, 62, 0, 54, 57, 56, 63, 59, + 63, 64, 65, 64, 65, 0, 66, 67, 66, 67, + 61, 60, 68, 71, 68, 71, 0, 62, 66, 65, + 70, 64, 70, 67, 0, 69, 63, 69, 68, 71, + + 72, 69, 72, 73, 70, 73, 74, 75, 74, 75, + 76, 77, 76, 77, 78, 0, 78, 72, 0, 79, + 73, 79, 74, 75, 76, 80, 81, 80, 81, 0, + 82, 77, 82, 0, 83, 78, 83, 84, 85, 84, + 85, 86, 81, 86, 87, 88, 87, 88, 83, 89, + 90, 89, 90, 91, 92, 91, 92, 93, 0, 93, + 94, 90, 94, 0, 89, 84, 95, 94, 95, 96, + 92, 96, 97, 98, 97, 98, 100, 99, 100, 99, + 0, 101, 96, 101, 0, 0, 0, 0, 0, 98, + 97, 99, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 100, 103, 103, 103, 105, 105, 106, 106, + 106, 106, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102 + } ; + +static ace_yy_state_type ace_yy_last_accepting_state; +static char *ace_yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define ace_yymore() ace_yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *ace_yytext; +# line 1 "Svc_Conf.l" +# line 2 "Svc_Conf.l" +// Sample lexical analysis for regular expression subset. Must be +// compiled with FLEX and an ANSI C++ compiler. + +// Lexical tokens values defined by YACC. +#include "ace/Svc_Conf.h" +#include "ace/Svc_Conf_Tokens.h" + +// Keeps track of the current line for debugging output. +int ace_yylineno = 1; + +// Keeps track of the number of errors encountered so far. +int ace_yyerrno = 0; + +#define token(x) x + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( ace_yytext, ace_yyleng, 1, ace_yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( ace_yy_current_buffer->ace_yy_is_interactive ) \ + { \ + int c = getc( ace_yyin ); \ + result = c == EOF ? 0 : 1; \ + buf[0] = (char) c; \ + } \ + else if ( ((result = fread( buf, 1, max_size, ace_yyin )) == 0) \ + && ferror( ace_yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "ace_yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef ace_yyterminate +#define ace_yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) ace_yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int ace_yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after ace_yytext and ace_yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +YY_DECL + { + register ace_yy_state_type ace_yy_current_state; + register char *ace_yy_cp, *ace_yy_bp; + register int ace_yy_act; + +# line 32 "Svc_Conf.l" + + + + if ( ace_yy_init ) + { +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! ace_yy_start ) + ace_yy_start = 1; /* first start state */ + + if ( ! ace_yyin ) + ace_yyin = stdin; + + if ( ! ace_yyout ) + ace_yyout = stdout; + + if ( ace_yy_current_buffer ) + ace_yy_init_buffer( ace_yy_current_buffer, ace_yyin ); + else + ace_yy_current_buffer = + ace_yy_create_buffer( ace_yyin, YY_BUF_SIZE ); + + ace_yy_load_buffer_state(); + + ace_yy_init = 0; + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + ace_yy_cp = ace_yy_c_buf_p; + + /* Support of ace_yytext. */ + *ace_yy_cp = ace_yy_hold_char; + + /* ace_yy_bp points to the position in ace_yy_ch_buf of the start of + * the current run. + */ + ace_yy_bp = ace_yy_cp; + + ace_yy_current_state = ace_yy_start; + if ( ace_yy_bp[-1] == '\n' ) + ++ace_yy_current_state; +ace_yy_match: + do + { + register YY_CHAR ace_yy_c = ace_yy_ec[YY_SC_TO_UI(*ace_yy_cp)]; + if ( ace_yy_accept[ace_yy_current_state] ) + { + ace_yy_last_accepting_state = ace_yy_current_state; + ace_yy_last_accepting_cpos = ace_yy_cp; + } + while ( ace_yy_chk[ace_yy_base[ace_yy_current_state] + ace_yy_c] != ace_yy_current_state ) + { + ace_yy_current_state = (int) ace_yy_def[ace_yy_current_state]; + if ( ace_yy_current_state >= 103 ) + ace_yy_c = ace_yy_meta[(unsigned int) ace_yy_c]; + } + ace_yy_current_state = ace_yy_nxt[ace_yy_base[ace_yy_current_state] + (unsigned int) ace_yy_c]; + ++ace_yy_cp; + } + while ( ace_yy_base[ace_yy_current_state] != 313 ); + +ace_yy_find_action: + ace_yy_act = ace_yy_accept[ace_yy_current_state]; + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( ace_yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *ace_yy_cp = ace_yy_hold_char; + ace_yy_cp = ace_yy_last_accepting_cpos; + ace_yy_current_state = ace_yy_last_accepting_state; + goto ace_yy_find_action; + +case 1: +*ace_yy_cp = ace_yy_hold_char; /* undo effects of setting up ace_yytext */ +ace_yy_c_buf_p = ace_yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up ace_yytext again */ +YY_USER_ACTION +# line 34 "Svc_Conf.l" +; /* EMPTY */ + YY_BREAK +case 2: +YY_USER_ACTION +# line 35 "Svc_Conf.l" +{ return token (ACE_DYNAMIC); } + YY_BREAK +case 3: +YY_USER_ACTION +# line 36 "Svc_Conf.l" +{ return token (ACE_STATIC); } + YY_BREAK +case 4: +YY_USER_ACTION +# line 37 "Svc_Conf.l" +{ return token (ACE_SUSPEND); } + YY_BREAK +case 5: +YY_USER_ACTION +# line 38 "Svc_Conf.l" +{ return token (ACE_RESUME); } + YY_BREAK +case 6: +YY_USER_ACTION +# line 39 "Svc_Conf.l" +{ return token (ACE_REMOVE); } + YY_BREAK +case 7: +YY_USER_ACTION +# line 40 "Svc_Conf.l" +{ return token (ACE_USTREAM); } + YY_BREAK +case 8: +YY_USER_ACTION +# line 41 "Svc_Conf.l" +{ return token (ACE_MODULE_T); } + YY_BREAK +case 9: +YY_USER_ACTION +# line 42 "Svc_Conf.l" +{ return token (ACE_SVC_OBJ_T); } + YY_BREAK +case 10: +YY_USER_ACTION +# line 43 "Svc_Conf.l" +{ return token (ACE_STREAM_T); } + YY_BREAK +case 11: +YY_USER_ACTION +# line 44 "Svc_Conf.l" +{ return token (ACE_ACTIVE); } + YY_BREAK +case 12: +YY_USER_ACTION +# line 45 "Svc_Conf.l" +{ return token (ACE_INACTIVE); } + YY_BREAK +case 13: +YY_USER_ACTION +# line 46 "Svc_Conf.l" +{ return token (ACE_COLON); } + YY_BREAK +case 14: +YY_USER_ACTION +# line 47 "Svc_Conf.l" +{ return token (ACE_STAR); } + YY_BREAK +case 15: +YY_USER_ACTION +# line 48 "Svc_Conf.l" +{ return token (ACE_LPAREN); } + YY_BREAK +case 16: +YY_USER_ACTION +# line 49 "Svc_Conf.l" +{ return token (ACE_RPAREN); } + YY_BREAK +case 17: +YY_USER_ACTION +# line 50 "Svc_Conf.l" +{ return token (ACE_LBRACE); } + YY_BREAK +case 18: +YY_USER_ACTION +# line 51 "Svc_Conf.l" +{ return token (ACE_RBRACE); } + YY_BREAK +case 19: +YY_USER_ACTION +# line 52 "Svc_Conf.l" +{ // Eliminate the opening and closing double quotes + *strrchr (ace_yytext, '"') = '\0'; + ace_yyleng -= 1; + ace_yylval.ident_ = ace_obstack->copy (ace_yytext + 1, ace_yyleng); + return token (ACE_STRING); } + YY_BREAK +case 20: +YY_USER_ACTION +# line 57 "Svc_Conf.l" +{ + ace_yylval.ident_ = ace_obstack->copy (ace_yytext, ace_yyleng); + return token (ACE_IDENT); + } + YY_BREAK +case 21: +YY_USER_ACTION +# line 61 "Svc_Conf.l" +{ + ace_yylval.ident_ = ace_obstack->copy (ace_yytext, ace_yyleng); + return token (ACE_PATHNAME); + } + YY_BREAK +case 22: +YY_USER_ACTION +# line 65 "Svc_Conf.l" +; /* EMPTY */ + YY_BREAK +case 23: +YY_USER_ACTION +# line 66 "Svc_Conf.l" +{ ace_yylineno++; } + YY_BREAK +case 24: +YY_USER_ACTION +# line 67 "Svc_Conf.l" +{ ACE_ERROR ((LM_ERROR, "unknown char = %d\n", *ace_yytext)); } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(PARAMETERS): +case YY_STATE_EOF(NORMAL): +# line 68 "Svc_Conf.l" +{ YY_NEW_FILE; ace_yyterminate(); } + YY_BREAK +case 25: +YY_USER_ACTION +# line 69 "Svc_Conf.l" +ECHO; + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int ace_yy_amount_of_matched_text = ace_yy_cp - ace_yytext_ptr - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *ace_yy_cp = ace_yy_hold_char; + + if ( ace_yy_current_buffer->ace_yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed ace_yyin at a new source and called + * ace_yylex(). If so, then we have to assure + * consistency between ace_yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + ace_yy_n_chars = ace_yy_current_buffer->ace_yy_n_chars; + ace_yy_current_buffer->ace_yy_input_file = ace_yyin; + ace_yy_current_buffer->ace_yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for ace_yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since ace_yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( ace_yy_c_buf_p <= &ace_yy_current_buffer->ace_yy_ch_buf[ace_yy_n_chars] ) + { /* This was really a NUL. */ + ace_yy_state_type ace_yy_next_state; + + ace_yy_c_buf_p = ace_yytext_ptr + ace_yy_amount_of_matched_text; + + ace_yy_current_state = ace_yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * ace_yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + ace_yy_next_state = ace_yy_try_NUL_trans( ace_yy_current_state ); + + ace_yy_bp = ace_yytext_ptr + YY_MORE_ADJ; + + if ( ace_yy_next_state ) + { + /* Consume the NUL. */ + ace_yy_cp = ++ace_yy_c_buf_p; + ace_yy_current_state = ace_yy_next_state; + goto ace_yy_match; + } + + else + { + ace_yy_cp = ace_yy_c_buf_p; + goto ace_yy_find_action; + } + } + + else switch ( ace_yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + ace_yy_did_buffer_switch_on_eof = 0; + + if ( ace_yywrap() ) + { + /* Note: because we've taken care in + * ace_yy_get_next_buffer() to have set up + * ace_yytext, we can now set up + * ace_yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + ace_yy_c_buf_p = ace_yytext_ptr + YY_MORE_ADJ; + + ace_yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! ace_yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + ace_yy_c_buf_p = + ace_yytext_ptr + ace_yy_amount_of_matched_text; + + ace_yy_current_state = ace_yy_get_previous_state(); + + ace_yy_cp = ace_yy_c_buf_p; + ace_yy_bp = ace_yytext_ptr + YY_MORE_ADJ; + goto ace_yy_match; + + case EOB_ACT_LAST_MATCH: + ace_yy_c_buf_p = + &ace_yy_current_buffer->ace_yy_ch_buf[ace_yy_n_chars]; + + ace_yy_current_state = ace_yy_get_previous_state(); + + ace_yy_cp = ace_yy_c_buf_p; + ace_yy_bp = ace_yytext_ptr + YY_MORE_ADJ; + goto ace_yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of ace_yylex */ + + +/* ace_yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int ace_yy_get_next_buffer() + { + register char *dest = ace_yy_current_buffer->ace_yy_ch_buf; + register char *source = ace_yytext_ptr - 1; /* copy prev. char, too */ + register int number_to_move, i; + int ret_val; + + if ( ace_yy_c_buf_p > &ace_yy_current_buffer->ace_yy_ch_buf[ace_yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( ace_yy_current_buffer->ace_yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( ace_yy_c_buf_p - ace_yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = ace_yy_c_buf_p - ace_yytext_ptr; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( ace_yy_current_buffer->ace_yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + ace_yy_n_chars = 0; + + else + { + int num_to_read = + ace_yy_current_buffer->ace_yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = ace_yy_current_buffer; + + int ace_yy_c_buf_p_offset = ace_yy_c_buf_p - b->ace_yy_ch_buf; + + b->ace_yy_buf_size *= 2; + b->ace_yy_ch_buf = (char *) + ace_yy_flex_realloc( (void *) b->ace_yy_ch_buf, + b->ace_yy_buf_size ); + + if ( ! b->ace_yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + ace_yy_c_buf_p = &b->ace_yy_ch_buf[ace_yy_c_buf_p_offset]; + + num_to_read = ace_yy_current_buffer->ace_yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&ace_yy_current_buffer->ace_yy_ch_buf[number_to_move]), + ace_yy_n_chars, num_to_read ); + } + + if ( ace_yy_n_chars == 0 ) + { + if ( number_to_move - YY_MORE_ADJ == 1 ) + { + ret_val = EOB_ACT_END_OF_FILE; + ace_yyrestart( ace_yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + ace_yy_current_buffer->ace_yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + ace_yy_n_chars += number_to_move; + ace_yy_current_buffer->ace_yy_ch_buf[ace_yy_n_chars] = YY_END_OF_BUFFER_CHAR; + ace_yy_current_buffer->ace_yy_ch_buf[ace_yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + /* ace_yytext begins at the second character in ace_yy_ch_buf; the first + * character is the one which preceded it before reading in the latest + * buffer; it needs to be kept around in case it's a newline, so + * ace_yy_get_previous_state() will have with '^' rules active. + */ + + ace_yytext_ptr = &ace_yy_current_buffer->ace_yy_ch_buf[1]; + + return ret_val; + } + + +/* ace_yy_get_previous_state - get the state just before the EOB char was reached */ + +static ace_yy_state_type ace_yy_get_previous_state() + { + register ace_yy_state_type ace_yy_current_state; + register char *ace_yy_cp; + + register char *ace_yy_bp = ace_yytext_ptr; + + ace_yy_current_state = ace_yy_start; + if ( ace_yy_bp[-1] == '\n' ) + ++ace_yy_current_state; + + for ( ace_yy_cp = ace_yytext_ptr + YY_MORE_ADJ; ace_yy_cp < ace_yy_c_buf_p; ++ace_yy_cp ) + { + register YY_CHAR ace_yy_c = (*ace_yy_cp ? ace_yy_ec[YY_SC_TO_UI(*ace_yy_cp)] : 1); + if ( ace_yy_accept[ace_yy_current_state] ) + { + ace_yy_last_accepting_state = ace_yy_current_state; + ace_yy_last_accepting_cpos = ace_yy_cp; + } + while ( ace_yy_chk[ace_yy_base[ace_yy_current_state] + ace_yy_c] != ace_yy_current_state ) + { + ace_yy_current_state = (int) ace_yy_def[ace_yy_current_state]; + if ( ace_yy_current_state >= 103 ) + ace_yy_c = ace_yy_meta[(unsigned int) ace_yy_c]; + } + ace_yy_current_state = ace_yy_nxt[ace_yy_base[ace_yy_current_state] + (unsigned int) ace_yy_c]; + } + + return ace_yy_current_state; + } + + +/* ace_yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = ace_yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static ace_yy_state_type ace_yy_try_NUL_trans( ace_yy_state_type ace_yy_current_state ) +#else +static ace_yy_state_type ace_yy_try_NUL_trans( ace_yy_current_state ) +ace_yy_state_type ace_yy_current_state; +#endif + { + register int ace_yy_is_jam; + register char *ace_yy_cp = ace_yy_c_buf_p; + + register YY_CHAR ace_yy_c = 1; + if ( ace_yy_accept[ace_yy_current_state] ) + { + ace_yy_last_accepting_state = ace_yy_current_state; + ace_yy_last_accepting_cpos = ace_yy_cp; + } + while ( ace_yy_chk[ace_yy_base[ace_yy_current_state] + ace_yy_c] != ace_yy_current_state ) + { + ace_yy_current_state = (int) ace_yy_def[ace_yy_current_state]; + if ( ace_yy_current_state >= 103 ) + ace_yy_c = ace_yy_meta[(unsigned int) ace_yy_c]; + } + ace_yy_current_state = ace_yy_nxt[ace_yy_base[ace_yy_current_state] + (unsigned int) ace_yy_c]; + ace_yy_is_jam = (ace_yy_current_state == 102); + + return ace_yy_is_jam ? 0 : ace_yy_current_state; + } + + +#ifdef YY_USE_PROTOS +static void ace_yyunput( int c, register char *ace_yy_bp ) +#else +static void ace_yyunput( c, ace_yy_bp ) +int c; +register char *ace_yy_bp; +#endif + { + register char *ace_yy_cp = ace_yy_c_buf_p; + + /* undo effects of setting up ace_yytext */ + *ace_yy_cp = ace_yy_hold_char; + + if ( ace_yy_cp < ace_yy_current_buffer->ace_yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = ace_yy_n_chars + 2; + register char *dest = &ace_yy_current_buffer->ace_yy_ch_buf[ + ace_yy_current_buffer->ace_yy_buf_size + 2]; + register char *source = + &ace_yy_current_buffer->ace_yy_ch_buf[number_to_move]; + + while ( source > ace_yy_current_buffer->ace_yy_ch_buf ) + *--dest = *--source; + + ace_yy_cp += dest - source; + ace_yy_bp += dest - source; + ace_yy_n_chars = ace_yy_current_buffer->ace_yy_buf_size; + + if ( ace_yy_cp < ace_yy_current_buffer->ace_yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + if ( ace_yy_cp > ace_yy_bp && ace_yy_cp[-1] == '\n' ) + ace_yy_cp[-2] = '\n'; + + *--ace_yy_cp = (char) c; + + + /* Note: the formal parameter *must* be called "ace_yy_bp" for this + * macro to now work correctly. + */ + YY_DO_BEFORE_ACTION; /* set up ace_yytext again */ + } + + +#ifdef __cplusplus +static int ace_yyinput() +#else +static int input() +#endif + { + int c; + + *ace_yy_c_buf_p = ace_yy_hold_char; + + if ( *ace_yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* ace_yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( ace_yy_c_buf_p < &ace_yy_current_buffer->ace_yy_ch_buf[ace_yy_n_chars] ) + /* This was really a NUL. */ + *ace_yy_c_buf_p = '\0'; + + else + { /* need more input */ + ace_yytext_ptr = ace_yy_c_buf_p; + ++ace_yy_c_buf_p; + + switch ( ace_yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( ace_yywrap() ) + { + ace_yy_c_buf_p = + ace_yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + YY_NEW_FILE; +#ifdef __cplusplus + return ace_yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + ace_yy_c_buf_p = ace_yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in ace_yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) ace_yy_c_buf_p; /* cast for 8-bit char's */ + *ace_yy_c_buf_p = '\0'; /* preserve ace_yytext */ + ace_yy_hold_char = *++ace_yy_c_buf_p; + + return c; + } + + +#ifdef YY_USE_PROTOS +void ace_yyrestart( FILE *input_file ) +#else +void ace_yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! ace_yy_current_buffer ) + ace_yy_current_buffer = ace_yy_create_buffer( ace_yyin, YY_BUF_SIZE ); + + ace_yy_init_buffer( ace_yy_current_buffer, input_file ); + ace_yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void ace_yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void ace_yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( ace_yy_current_buffer == new_buffer ) + return; + + if ( ace_yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *ace_yy_c_buf_p = ace_yy_hold_char; + ace_yy_current_buffer->ace_yy_buf_pos = ace_yy_c_buf_p; + ace_yy_current_buffer->ace_yy_n_chars = ace_yy_n_chars; + } + + ace_yy_current_buffer = new_buffer; + ace_yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (ace_yywrap()) processing, but the only time this flag + * is looked at is after ace_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + ace_yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void ace_yy_load_buffer_state( void ) +#else +void ace_yy_load_buffer_state() +#endif + { + ace_yy_n_chars = ace_yy_current_buffer->ace_yy_n_chars; + ace_yytext_ptr = ace_yy_c_buf_p = ace_yy_current_buffer->ace_yy_buf_pos; + ace_yyin = ace_yy_current_buffer->ace_yy_input_file; + ace_yy_hold_char = *ace_yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE ace_yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE ace_yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) ace_yy_flex_alloc( sizeof( struct ace_yy_buffer_state ) ); + + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ace_yy_create_buffer()" ); + + b->ace_yy_buf_size = size; + + /* ace_yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->ace_yy_ch_buf = (char *) ace_yy_flex_alloc( b->ace_yy_buf_size + 2 ); + + if ( ! b->ace_yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in ace_yy_create_buffer()" ); + + ace_yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void ace_yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void ace_yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( b == ace_yy_current_buffer ) + ace_yy_current_buffer = (YY_BUFFER_STATE) 0; + + ace_yy_flex_free( (void *) b->ace_yy_ch_buf ); + ace_yy_flex_free( (void *) b ); + } + + +#ifdef YY_USE_PROTOS +void ace_yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void ace_yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + { + b->ace_yy_input_file = file; + + /* We put in the '\n' and start reading from [1] so that an + * initial match-at-newline will be true. + */ + + b->ace_yy_ch_buf[0] = '\n'; + b->ace_yy_n_chars = 1; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->ace_yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + b->ace_yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR; + + b->ace_yy_buf_pos = &b->ace_yy_ch_buf[1]; + + b->ace_yy_is_interactive = file ? isatty( fileno(file) ) : 0; + + b->ace_yy_fill_buffer = 1; + + b->ace_yy_buffer_status = YY_BUFFER_NEW; + } + + +#ifdef YY_USE_PROTOS +static void ace_yy_push_state( int new_state ) +#else +static void ace_yy_push_state( new_state ) +int new_state; +#endif + { + if ( ace_yy_start_stack_ptr >= ace_yy_start_stack_depth ) + { + int new_size; + + ace_yy_start_stack_depth += YY_START_STACK_INCR; + new_size = ace_yy_start_stack_depth * sizeof( int ); + + if ( ! ace_yy_start_stack ) + ace_yy_start_stack = (int *) ace_yy_flex_alloc( new_size ); + + else + ace_yy_start_stack = (int *) ace_yy_flex_realloc( + (void *) ace_yy_start_stack, new_size ); + + if ( ! ace_yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + ace_yy_start_stack[ace_yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } + + +static void ace_yy_pop_state() + { + if ( --ace_yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(ace_yy_start_stack[ace_yy_start_stack_ptr]); + } + + +static int ace_yy_top_state() + { + return ace_yy_start_stack[ace_yy_start_stack_ptr - 1]; + } + + +#ifdef YY_USE_PROTOS +static void ace_yy_fatal_error( const char msg[] ) +#else +static void ace_yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( 1 ); + } + + + +/* Redefine ace_yyless() so it works in section 3 code. */ + +#undef ace_yyless +#define ace_yyless(n) \ + do \ + { \ + /* Undo effects of setting up ace_yytext. */ \ + ace_yytext[ace_yyleng] = ace_yy_hold_char; \ + ace_yy_c_buf_p = ace_yytext + n - YY_MORE_ADJ; \ + ace_yy_hold_char = *ace_yy_c_buf_p; \ + *ace_yy_c_buf_p = '\0'; \ + ace_yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef ace_yytext_ptr +#ifdef YY_USE_PROTOS +static void ace_yy_flex_strncpy( char *s1, const char *s2, int n ) +#else +static void ace_yy_flex_strncpy( s1, s2, n ) +char *s1; +const char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *ace_yy_flex_alloc( unsigned int size ) +#else +static void *ace_yy_flex_alloc( size ) +unsigned int size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *ace_yy_flex_realloc( void *ptr, unsigned int size ) +#else +static void *ace_yy_flex_realloc( ptr, size ) +void *ptr; +unsigned int size; +#endif + { + return (void *) realloc( ACE_MALLOC_T (ptr), size ); + } + +#ifdef YY_USE_PROTOS +static void ace_yy_flex_free( void *ptr ) +#else +static void ace_yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ACE_MALLOC_T (ptr) ); + } +# line 69 "Svc_Conf.l" + +int +ace_yywrap (void) +{ + ::fflush (ace_yyin); + ace_yytext[0] = '#'; + ace_yyleng = 0; + return 1; +} diff --git a/ace/Svc_Conf_y.cpp b/ace/Svc_Conf_y.cpp new file mode 100644 index 00000000000..b094b72247d --- /dev/null +++ b/ace/Svc_Conf_y.cpp @@ -0,0 +1,923 @@ +#ifndef lint +// @(#)Svc_Conf_y.cpp 1.1 10/18/96 + +char ace_yysccsid[] = "@(#)yaccpar 1.4 (Berkeley) 02/25/90 \n\ + Modified 5/2/90 by J. Roskind to support graphic debugging modes"; +#endif +#line 2 "Svc_Conf.y" +#define ACE_BUILD_DLL +#include "ace/ARGV.h" +#include "ace/Svc_Conf.h" +#include "ace/Module.h" +#include "ace/Stream.h" + +static ACE_Module_Type *get_module (ACE_Static_Node *str_rec, ACE_Static_Node *svc_type); +static ACE_Module_Type *get_module (ACE_Static_Node *str_rec, const char *svc_name); + +#define YYDEBUG_LEXER_TEXT (ace_yytext[ace_yyleng] = '\0', ace_yytext) +/* Force the pretty debugging code to compile.*/ +#define YYDEBUG 1 + +/* Efficient memory allocation technique.*/ +ACE_Obstack *ace_obstack; + +#line 23 "y.tab.c" +#define ACE_DYNAMIC 257 +#define ACE_STATIC 258 +#define ACE_SUSPEND 259 +#define ACE_RESUME 260 +#define ACE_REMOVE 261 +#define ACE_USTREAM 262 +#define ACE_MODULE_T 263 +#define ACE_STREAM_T 264 +#define ACE_SVC_OBJ_T 265 +#define ACE_ACTIVE 266 +#define ACE_INACTIVE 267 +#define ACE_PATHNAME 268 +#define ACE_IDENT 269 +#define ACE_STRING 270 +#define ACE_LPAREN 271 +#define ACE_RPAREN 272 +#define ACE_LBRACE 273 +#define ACE_RBRACE 274 +#define ACE_STAR 275 +#define ACE_COLON 276 +#define YYERRCODE 256 +short ace_yylhs[] = { -1, + 0, 0, 0, 13, 13, 13, 13, 13, 13, 4, + 5, 6, 7, 8, 10, 17, 10, 14, 14, 18, + 11, 11, 9, 9, 12, 12, 12, 12, 12, 15, + 3, 3, 3, 16, 16, 2, 2, 2, 1, 1, +}; +short ace_yylen[] = { 2, + 2, 2, 0, 1, 1, 1, 1, 1, 1, 3, + 3, 2, 2, 2, 3, 0, 4, 1, 1, 0, + 4, 0, 2, 0, 1, 1, 1, 1, 1, 4, + 1, 1, 0, 3, 5, 2, 2, 2, 1, 0, +}; +short ace_yydefred[] = { 3, + 0, 2, 0, 0, 0, 0, 0, 0, 4, 5, + 6, 7, 8, 9, 1, 0, 0, 0, 12, 13, + 14, 16, 18, 19, 0, 0, 0, 0, 0, 39, + 10, 11, 0, 20, 15, 36, 38, 37, 0, 0, + 17, 24, 0, 31, 32, 30, 0, 0, 21, 25, + 26, 27, 28, 29, 23, 0, 35, +}; +short ace_yydgoto[] = { 1, + 31, 29, 46, 9, 10, 11, 12, 13, 47, 14, + 35, 55, 15, 25, 17, 40, 33, 42, +}; +short ace_yysindex[] = { 0, + -244, 0, -266, -260, -250, -243, -239, -247, 0, 0, + 0, 0, 0, 0, 0, -240, -237, -237, 0, 0, + 0, 0, 0, 0, -242, -241, -235, -233, -236, 0, + 0, 0, -242, 0, 0, 0, 0, 0, -232, -238, + 0, 0, -234, 0, 0, 0, -253, -228, 0, 0, + 0, 0, 0, 0, 0, -227, 0, +}; +short ace_yyrindex[] = { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27, 27, 0, 0, + 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, + 0, 0, 46, 0, 0, 0, 0, 0, 0, 20, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, +}; +short ace_yygindex[] = { 0, + 18, 0, 0, -8, -6, -10, -9, 2, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, +}; +#define YYTABLESIZE 308 +short ace_yytable[] = { 23, + 34, 24, 16, 3, 4, 5, 6, 7, 18, 3, + 4, 2, 3, 4, 5, 6, 7, 8, 19, 33, + 49, 22, 26, 27, 28, 20, 40, 44, 45, 21, + 34, 39, 30, 36, 48, 32, 52, 53, 50, 37, + 51, 38, 56, 43, 57, 22, 41, 0, 54, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, + 34, 34, 34, 0, 0, 0, 34, 34, 0, 0, + 34, 0, 0, 34, 34, 33, 33, 33, 33, 33, + 33, 33, 40, 40, 40, 40, 40, 40, 40, 33, + 0, 0, 33, 33, 0, 0, 0, 0, 0, 40, + 40, 22, 22, 22, 22, 22, 22, 22, +}; +short ace_yycheck[] = { 8, + 0, 8, 269, 257, 258, 259, 260, 261, 269, 257, + 258, 256, 257, 258, 259, 260, 261, 262, 269, 0, + 274, 269, 263, 264, 265, 269, 0, 266, 267, 269, + 273, 268, 270, 275, 269, 18, 47, 47, 47, 275, + 47, 275, 271, 276, 272, 0, 33, -1, 47, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 256, 257, 258, 259, + 260, 261, 262, -1, -1, -1, 266, 267, -1, -1, + 270, -1, -1, 273, 274, 256, 257, 258, 259, 260, + 261, 262, 256, 257, 258, 259, 260, 261, 262, 270, + -1, -1, 273, 274, -1, -1, -1, -1, -1, 273, + 274, 256, 257, 258, 259, 260, 261, 262, +}; +#define YYFINAL 1 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 276 +#if YYDEBUG +char *ace_yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"ACE_DYNAMIC","ACE_STATIC", +"ACE_SUSPEND","ACE_RESUME","ACE_REMOVE","ACE_USTREAM","ACE_MODULE_T", +"ACE_STREAM_T","ACE_SVC_OBJ_T","ACE_ACTIVE","ACE_INACTIVE","ACE_PATHNAME", +"ACE_IDENT","ACE_STRING","ACE_LPAREN","ACE_RPAREN","ACE_LBRACE","ACE_RBRACE", +"ACE_STAR","ACE_COLON", +}; +char *ace_yyrule[] = { +"$accept : svc_config_entries", +"svc_config_entries : svc_config_entries svc_config_entry", +"svc_config_entries : svc_config_entries error", +"svc_config_entries :", +"svc_config_entry : dynamic", +"svc_config_entry : static", +"svc_config_entry : suspend", +"svc_config_entry : resume", +"svc_config_entry : remove", +"svc_config_entry : stream", +"dynamic : ACE_DYNAMIC svc_location parameters_opt", +"static : ACE_STATIC ACE_IDENT parameters_opt", +"suspend : ACE_SUSPEND ACE_IDENT", +"resume : ACE_RESUME ACE_IDENT", +"remove : ACE_REMOVE ACE_IDENT", +"stream : ACE_USTREAM stream_ops stream_modules", +"$$1 :", +"stream : ACE_USTREAM ACE_IDENT $$1 stream_modules", +"stream_ops : dynamic", +"stream_ops : static", +"$$2 :", +"stream_modules : ACE_LBRACE $$2 module_list ACE_RBRACE", +"stream_modules :", +"module_list : module_list module", +"module_list :", +"module : dynamic", +"module : static", +"module : suspend", +"module : resume", +"module : remove", +"svc_location : ACE_IDENT type svc_initializer status", +"status : ACE_ACTIVE", +"status : ACE_INACTIVE", +"status :", +"svc_initializer : ACE_PATHNAME ACE_COLON ACE_IDENT", +"svc_initializer : ACE_PATHNAME ACE_COLON ACE_IDENT ACE_LPAREN ACE_RPAREN", +"type : ACE_MODULE_T ACE_STAR", +"type : ACE_SVC_OBJ_T ACE_STAR", +"type : ACE_STREAM_T ACE_STAR", +"parameters_opt : ACE_STRING", +"parameters_opt :", +}; +#endif +#define ace_yyclearin (ace_yychar=(-1)) +#define ace_yyerrok (ace_yyerrflag=0) +#ifndef YYSTACKSIZE +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 300 +#endif +#endif +int ace_yydebug; +int ace_yynerrs; +int ace_yyerrflag; +int ace_yychar; +short *ace_yyssp; +YYSTYPE *ace_yyvsp; +YYSTYPE ace_yyval; +YYSTYPE ace_yylval; +#define ace_yystacksize YYSTACKSIZE +short ace_yyss[YYSTACKSIZE]; +YYSTYPE ace_yyvs[YYSTACKSIZE]; +#line 241 "Svc_Conf.y" +// Prints the error string to standard output. Cleans up the error +// messages. + +void +ace_yyerror (char *s) +{ + ACE_ERROR ((LM_ERROR, "[error %d] on line %d: %s\n", + ++ace_yyerrno, ace_yylineno, s)); +} + +// Note that SRC_REC represents left context, which is the STREAM * +// record. + +static ACE_Module_Type * +get_module (ACE_Static_Node *str_rec, const char *svc_name) +{ + const ACE_Service_Record *sr = str_rec->record (); + const ACE_Service_Type *type = sr->type (); + ACE_Stream_Type *st = sr == 0 ? 0 : (ACE_Stream_Type *) type; + ACE_Module_Type *mt = st == 0 ? 0 : st->find (svc_name); + + if (sr == 0 || st == 0 || mt == 0) + { + ACE_ERROR ((LM_ERROR, "cannot locate Module_Type %s in STREAM_Type %s\n", + svc_name, str_rec->name ())); + ace_yyerrno++; + } + return mt; +} + +static ACE_Module_Type * +get_module (ACE_Static_Node *str_rec, ACE_Static_Node *svc_type) +{ + const ACE_Service_Record *sr = str_rec->record (); + const ACE_Service_Type *type = sr->type (); + ACE_Stream_Type *st = sr == 0 ? 0 : (ACE_Stream_Type *) type; + const ACE_Service_Record *sv = svc_type->record (); + type = sv->type (); + ACE_Module_Type *mt = (ACE_Module_Type *) type; + + if (sr == 0 || st == 0 || mt == 0) + { + ACE_ERROR ((LM_ERROR, "cannot locate Module_Type %s or STREAM_Type %s\n", + svc_type->name (), str_rec->name ())); + ace_yyerrno++; + } + return mt; +} + +ACE_Service_Type * +ace_create_service_type (const char *name, + int type, + const void *symbol, + unsigned int flags) +{ + ACE_Service_Type *stp = 0; + + // Note, the only place we need to put a case statement. This is + // also the place where we'd put the RTTI tests, if the compiler + // actually supported them! + + switch (type) + { + case ACE_SVC_OBJ_T: + stp = new ACE_Service_Object_Type ((ACE_Service_Object *) symbol, name, flags); + break; + case ACE_MODULE_T: + stp = new ACE_Module_Type ((MT_Module *) symbol, name, flags); + break; + case ACE_STREAM_T: + stp = new ACE_Stream_Type ((MT_Stream *) symbol, name, flags); + break; + default: + ACE_ERROR ((LM_ERROR, "unknown case\n")); + ace_yyerrno++; + break; + } + return stp; +} + +#if defined (DEBUGGING) +// Current line number. +int ace_yylineno = 1; + +// Name given on the command-line to envoke the program. +char *program_name; + +// Main driver program. + +int +main (int argc, char *argv[]) +{ + ace_yyin = stdin; + ace_obstack = new ACE_Obstack; + + // Try to reopen any filename argument to use YYIN. + if (argc > 1 && (ace_yyin = freopen (argv[1], "r", stdin)) == 0) + (void) ::fprintf (stderr, "usage: %s [file]\n", argv[0]), exit (1); + + return ace_yyparse (); +} +#endif /* DEBUGGING */ +#line 342 "y.tab.c" +#define YYABORT goto ace_yyabort +#define YYACCEPT goto ace_yyaccept +#define YYERROR goto ace_yyerrlab +#ifdef YYDEBUG +#ifndef YYDEBUG_LEXER_TEXT /* pointer to the text isolated by the lexer*/ +#define YYDEBUG_LEXER_TEXT "YYDEBUG_LEXER_TEXT not defined" +#endif +#ifndef YYDEBUG_INDENT_STRING +#define YYDEBUG_INDENT_STRING "| " +#endif +#ifndef YYDEBUG_REDUCE_STRING +#define YYDEBUG_REDUCE_STRING "+-------" +#endif +#ifndef YYDEBUG_INDENT +#ifdef __cplusplus +void YYDEBUG_INDENT(int ace_yyindent) +#else +YYDEBUG_INDENT(ace_yyindent) +int ace_yyindent; +#endif +{ + while(ace_yyindent-- > 0) + printf("%s", YYDEBUG_INDENT_STRING); +} +#endif /* YYDEBUG_INDENT */ +#ifndef YYDEBUG_REDUCE +#ifdef __cplusplus +void YYDEBUG_REDUCE(int ace_yynew_state, int ace_yyrule_num, char *ace_yyrule_string, int ace_yynew_indent, int ace_yyrhs_count) +#else +YYDEBUG_REDUCE(ace_yynew_state, ace_yyrule_num, ace_yyrule_string, ace_yynew_indent, ace_yyrhs_count) +int ace_yynew_state; +int ace_yyrule_num; +char * ace_yyrule_string; +int ace_yynew_indent; +int ace_yyrhs_count; +#endif +{ + if (1 < ace_yyrhs_count) + { /* draw the graphics for the reduction */ + YYDEBUG_INDENT(ace_yynew_indent); + while(1 < ace_yyrhs_count--) + printf("%s", YYDEBUG_REDUCE_STRING); + putchar('+'); /* left rotated L would look nice */ + putchar('\n'); + YYDEBUG_INDENT(ace_yynew_indent); + putchar('|'); /* down arrow would look nice */ + putchar('\n'); + } + YYDEBUG_INDENT(ace_yynew_indent); + /* Only print the resulting token name */ + while (*ace_yyrule_string) + putchar(*ace_yyrule_string++); + putchar('\n'); +} +#endif /* YYDEBUG_REDUCE */ +#ifndef YYDEBUG_SHIFT_LEXEME +#ifdef __cplusplus +void YYDEBUG_SHIFT_LEXEME(int ace_yyold_state, int ace_yynew_state, char *ace_yytoken_string, int ace_yynew_indent) +#else +YYDEBUG_SHIFT_LEXEME(ace_yyold_state, ace_yynew_state, ace_yytoken_string, ace_yynew_indent) +int ace_yyold_state; +int ace_yynew_state; +char * ace_yytoken_string; +int ace_yynew_indent; +#endif +{ + YYDEBUG_INDENT(ace_yynew_indent); + printf("%s <-- `%s'\n", ace_yytoken_string, YYDEBUG_LEXER_TEXT); +} +#endif /* YYDEBUG_SHIFT_LEXEME */ +#ifndef YYDEBUG_LOOK_AHEAD +#ifdef __cplusplus +void YYDEBUG_LOOK_AHEAD(int ace_yynew_state, int ace_yytoken_num, char *ace_yytoken_string, int ace_yyindent) +#else +YYDEBUG_LOOK_AHEAD(ace_yynew_state, ace_yytoken_num, ace_yytoken_string, ace_yyindent) +int ace_yynew_state; +int ace_yytoken_num; +char * ace_yytoken_string; +int ace_yyindent; +#endif +{ + YYDEBUG_INDENT(ace_yyindent); + printf(" .... look ahead at %s `%s'\n", + ace_yytoken_string, + (0 == ace_yytoken_num)? "\0": YYDEBUG_LEXER_TEXT); +} +#endif /* YYDEBUG_LOOK_AHEAD */ +#ifndef YYDEBUG_DISCARD_STATE +#ifdef __cplusplus +void YYDEBUG_DISCARD_STATE(int ace_yynew_state, int ace_yyindent) +#else +YYDEBUG_DISCARD_STATE(ace_yynew_state, ace_yyindent) +int ace_yynew_state; +int ace_yyindent; +#endif +{ + if (0 < ace_yyindent) + { /* draw the graphics for the reduction */ + YYDEBUG_INDENT(ace_yyindent-1); + printf("%s", YYDEBUG_REDUCE_STRING); + putchar('+'); /* left rotated L would look nice */ + printf(" discarding state\n"); + YYDEBUG_INDENT(ace_yyindent-1); + putchar('|'); /* down arrow would look nice */ + putchar('\n'); + } + else + { + if (0 == ace_yyindent) + printf("discarding state\n"); + else + printf("no more states to discard: parser will abort\n"); + } +} +#endif /* YYDEBUG_DISCARD_STATE */ +#ifndef YYDEBUG_DISCARD_TOKEN +#ifdef __cplusplus +void YYDEBUG_DISCARD_TOKEN(int ace_yynew_state, int ace_yytoken_num, char *ace_yytoken_string, int ace_yyindent) +#else +YYDEBUG_DISCARD_TOKEN(ace_yynew_state, ace_yytoken_num, ace_yytoken_string, ace_yyindent) +int ace_yynew_state; +int ace_yytoken_num; +char * ace_yytoken_string; +int ace_yyindent; +#endif +{ + YYDEBUG_INDENT(ace_yyindent); + printf("discarding token %s\n", ace_yytoken_string); +} +#endif /* YYDEBUG_DISCARD_TOKEN */ +#ifndef YYDEBUG_SHIFT_ERROR_LEXEME +#ifdef __cplusplus +void YYDEBUG_SHIFT_ERROR_LEXEME(int ace_yyold_state, int ace_yynew_state, int ace_yyindent) +#else +YYDEBUG_SHIFT_ERROR_LEXEME(ace_yyold_state, ace_yynew_state, ace_yyindent) +int ace_yyold_state; +int ace_yynew_state; +int ace_yyindent; +#endif +{ + YYDEBUG_INDENT(ace_yyindent); + printf("error\n"); +} +#endif /* YYDEBUG_SHIFT_ERROR_LEXEME */ +#endif /* YYDEBUG */ +#ifdef __cplusplus +extern "C" { extern char *getenv(const char *); } +#endif +int +ace_yyparse() +{ + register int ace_yym, ace_yyn, ace_yystate; +#if YYDEBUG + register char *ace_yys; +#ifndef __cplusplus + extern char *getenv(); +#endif + + if (ace_yys = ACE_OS::getenv("YYDEBUG")) + { + ace_yyn = *ace_yys; + if (ace_yyn >= '0' && ace_yyn <= '9') + ace_yydebug = ace_yyn - '0'; + } +#endif + + ace_yynerrs = 0; + ace_yyerrflag = 0; + ace_yychar = (-1); + + ace_yyssp = ace_yyss; + ace_yyvsp = ace_yyvs; + *ace_yyssp = ace_yystate = 0; + +ace_yyloop: + if (ace_yyn = ace_yydefred[ace_yystate]) goto ace_yyreduce; + if (ace_yychar < 0) + { + if ((ace_yychar = ace_yylex()) < 0) ace_yychar = 0; +#if YYDEBUG + if (ace_yydebug) + { + ace_yys = 0; + if (ace_yychar <= YYMAXTOKEN) ace_yys = ace_yyname[ace_yychar]; + if (!ace_yys) ace_yys = "illegal-symbol"; + if (5 < ace_yydebug) + printf("ace_yydebug: state %d, reading %d (%s)\n", ace_yystate, + ace_yychar, ace_yys); + else + YYDEBUG_LOOK_AHEAD(ace_yystate, ace_yychar, ace_yys, ace_yyssp-ace_yyss); + } +#endif + } + if ((ace_yyn = ace_yysindex[ace_yystate]) && (ace_yyn += ace_yychar) >= 0 && + ace_yyn <= YYTABLESIZE && ace_yycheck[ace_yyn] == ace_yychar) + { +#if YYDEBUG + if (ace_yydebug) + if (5 < ace_yydebug) + printf("ace_yydebug: state %d, shifting to state %d\n", + ace_yystate, ace_yytable[ace_yyn]); + else + YYDEBUG_SHIFT_LEXEME(ace_yystate, ace_yytable[ace_yyn], ace_yys, ace_yyssp-ace_yyss); +#endif + if (ace_yyssp >= ace_yyss + ace_yystacksize - 1) + { + goto ace_yyoverflow; + } + *++ace_yyssp = ace_yystate = ace_yytable[ace_yyn]; + *++ace_yyvsp = ace_yylval; + ace_yychar = (-1); + if (ace_yyerrflag > 0) --ace_yyerrflag; + goto ace_yyloop; + } + if ((ace_yyn = ace_yyrindex[ace_yystate]) && (ace_yyn += ace_yychar) >= 0 && + ace_yyn <= YYTABLESIZE && ace_yycheck[ace_yyn] == ace_yychar) + { + ace_yyn = ace_yytable[ace_yyn]; + goto ace_yyreduce; + } + if (ace_yyerrflag) goto ace_yyinrecovery; +#ifdef lint + goto ace_yynewerror; +#endif + + ace_yyerror("syntax error"); +#ifdef lint + goto ace_yyerrlab; +#endif + + ++ace_yynerrs; +ace_yyinrecovery: + if (ace_yyerrflag < 3) + { + ace_yyerrflag = 3; + for (;;) + { + if ((ace_yyn = ace_yysindex[*ace_yyssp]) && (ace_yyn += YYERRCODE) >= 0 && + ace_yyn <= YYTABLESIZE && ace_yycheck[ace_yyn] == YYERRCODE) + { +#if YYDEBUG + if (ace_yydebug) + if (5 < ace_yydebug) + printf("ace_yydebug: state %d, error recovery shifting\ + to state %d\n", *ace_yyssp, ace_yytable[ace_yyn]); + else + YYDEBUG_SHIFT_ERROR_LEXEME(*ace_yyssp, ace_yytable[ace_yyn], ace_yyssp-ace_yyss); +#endif + if (ace_yyssp >= ace_yyss + ace_yystacksize - 1) + { + goto ace_yyoverflow; + } + *++ace_yyssp = ace_yystate = ace_yytable[ace_yyn]; + *++ace_yyvsp = ace_yylval; + goto ace_yyloop; + } + else + { +#if YYDEBUG + if (ace_yydebug) + if (5 < ace_yydebug) + printf("ace_yydebug: error recovery discarding state %d\ +", + *ace_yyssp); + else + YYDEBUG_DISCARD_STATE(*ace_yyssp, ace_yyssp-ace_yyss-1); +#endif + if (ace_yyssp <= ace_yyss) goto ace_yyabort; + --ace_yyssp; + --ace_yyvsp; + } + } + } + else + { + if (ace_yychar == 0) goto ace_yyabort; +#if YYDEBUG + if (ace_yydebug) + { + ace_yys = 0; + if (ace_yychar <= YYMAXTOKEN) ace_yys = ace_yyname[ace_yychar]; + if (!ace_yys) ace_yys = "illegal-symbol"; + if (5 < ace_yydebug) + printf("ace_yydebug: state %d, error recovery discards token %d (%s)\n", + ace_yystate, ace_yychar, ace_yys); + else + YYDEBUG_DISCARD_TOKEN(ace_yystate, ace_yychar, ace_yys, ace_yyssp-ace_yyss); + } +#endif + ace_yychar = (-1); + goto ace_yyloop; + } +ace_yyreduce: + ace_yym = ace_yylen[ace_yyn]; + ace_yyval = ace_yyvsp[1-ace_yym]; +#if YYDEBUG + if (ace_yydebug) + if (5 < ace_yydebug) + printf("ace_yydebug: state %d, reducing by rule %d (%s)\n", + ace_yystate, ace_yyn, ace_yyrule[ace_yyn]); + else + YYDEBUG_REDUCE(ace_yystate, ace_yyn, ace_yyrule[ace_yyn], ace_yyssp-ace_yyss-ace_yym, ace_yym); +#endif + switch (ace_yyn) + { +case 1: +#line 38 "Svc_Conf.y" +{ + ace_yyvsp[0].parse_node_->apply (); delete ace_yyvsp[0].parse_node_; ace_obstack->release (); + } +break; +case 2: +#line 42 "Svc_Conf.y" +{ + ace_obstack->release (); + } +break; +case 10: +#line 59 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Dynamic_Node (ace_yyvsp[-1].svc_record_, ace_yyvsp[0].ident_); + } +break; +case 11: +#line 66 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Static_Node (ace_yyvsp[-1].ident_, ace_yyvsp[0].ident_); + } +break; +case 12: +#line 73 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Suspend_Node (ace_yyvsp[0].ident_); + } +break; +case 13: +#line 80 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Resume_Node (ace_yyvsp[0].ident_); + } +break; +case 14: +#line 87 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Remove_Node (ace_yyvsp[0].ident_); + } +break; +case 15: +#line 94 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Stream_Node (ace_yyvsp[-1].ACE_Static_Node_, ace_yyvsp[0].parse_node_); + } +break; +case 16: +#line 97 "Svc_Conf.y" +{ ace_yyval.ACE_Static_Node_ = new ACE_Static_Node (ace_yyvsp[0].ident_); } +break; +case 17: +#line 98 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = new ACE_Dummy_Node (ace_yyvsp[-1].ACE_Static_Node_, ace_yyvsp[0].parse_node_); + } +break; +case 18: +#line 105 "Svc_Conf.y" +{ + } +break; +case 19: +#line 108 "Svc_Conf.y" +{ + } +break; +case 20: +#line 114 "Svc_Conf.y" +{ + /* Initialize left context...*/ + ace_yyval.ACE_Static_Node_ = ace_yyvsp[-1].ACE_Static_Node_; + } +break; +case 21: +#line 119 "Svc_Conf.y" +{ + ace_yyval.parse_node_ = ace_yyvsp[-1].parse_node_; + } +break; +case 22: +#line 122 "Svc_Conf.y" +{ ace_yyval.parse_node_ = 0; } +break; +case 23: +#line 126 "Svc_Conf.y" +{ ace_yyvsp[0].parse_node_->link (ace_yyvsp[-1].parse_node_); ace_yyval.parse_node_ = ace_yyvsp[0].parse_node_; } +break; +case 24: +#line 127 "Svc_Conf.y" +{ ace_yyval.parse_node_ = 0; } +break; +case 25: +#line 132 "Svc_Conf.y" +{ + ACE_ARGV args (ace_yyvsp[0].ACE_Static_Node_->parameters ()); + ACE_Module_Type *mt = get_module (ace_yyvsp[-2].ACE_Static_Node_, ace_yyvsp[0].ACE_Static_Node_); + + if (::strcmp (ace_yyvsp[0].ACE_Static_Node_->name (), + ((MT_Module *) mt->object ())->name ()) != 0) + ACE_ERROR ((LM_ERROR, "warning, service name %s is different from Module name %s\n", + ace_yyvsp[0].ACE_Static_Node_->name (), ((MT_Module *) mt->object ())->name ())); + + if (mt->init (args.argc (), args.argv ()) == -1 + || ((ACE_Stream_Type *) (ace_yyvsp[-2].ACE_Static_Node_)->record ()->type ())->push (mt) == -1) + { + ACE_ERROR ((LM_ERROR, "dynamic initialization failed for Module %s\n", + ace_yyvsp[0].ACE_Static_Node_->name ())); + ace_yyerrno++; + } + } +break; +case 26: +#line 150 "Svc_Conf.y" +{ + ACE_Module_Type *mt = get_module (ace_yyvsp[-2].ACE_Static_Node_, ace_yyvsp[0].ACE_Static_Node_->name ()); + if (::strcmp (ace_yyvsp[0].ACE_Static_Node_->name (), + ((MT_Module *) mt->object ())->name ()) != 0) + ACE_ERROR ((LM_ERROR, "warning, service name %s is different from Module name %s\n", + ace_yyvsp[0].ACE_Static_Node_->name (), ((MT_Module *) mt->object ())->name ())); + if (((ACE_Stream_Type *) (ace_yyvsp[-2].ACE_Static_Node_)->record ()->type ())->push (mt) == -1) + ace_yyerrno++; + } +break; +case 27: +#line 160 "Svc_Conf.y" +{ + ACE_Module_Type *mt = get_module (ace_yyvsp[-2].ACE_Static_Node_, ace_yyvsp[0].ACE_Static_Node_->name ()); + if (mt != 0) + mt->suspend (); + } +break; +case 28: +#line 166 "Svc_Conf.y" +{ + ACE_Module_Type *mt = get_module (ace_yyvsp[-2].ACE_Static_Node_, ace_yyvsp[0].ACE_Static_Node_->name ()); + if (mt != 0) + mt->resume (); + } +break; +case 29: +#line 172 "Svc_Conf.y" +{ + ACE_Module_Type *mt = get_module (ace_yyvsp[-2].ACE_Static_Node_, ace_yyvsp[0].ACE_Static_Node_->name ()); + if (mt != 0 + && ((ACE_Stream_Type *) (ace_yyvsp[-2].ACE_Static_Node_)->record ()->type ())->remove (mt) == -1) + { + ACE_ERROR ((LM_ERROR, "cannot remove Module_Type %s from STREAM_Type %s\n", + ace_yyvsp[0].ACE_Static_Node_->name (), (ace_yyvsp[-2].ACE_Static_Node_)->name ())); + ace_yyerrno++; + } + } +break; +case 30: +#line 186 "Svc_Conf.y" +{ + unsigned int flags + = ACE_Service_Type::DELETE_THIS | (ace_yyvsp[-1].location_node_->dispose () == 0 ? 0 : ACE_Service_Type::DELETE_OBJ); + ACE_Service_Type *stp = ace_create_service_type (ace_yyvsp[-3].ident_, ace_yyvsp[-2].type_, ace_yyvsp[-1].location_node_->symbol (), flags); + ace_yyval.svc_record_ = new ACE_Service_Record (ace_yyvsp[-3].ident_, stp, ace_yyvsp[-1].location_node_->handle (), ace_yyvsp[0].type_); + } +break; +case 31: +#line 196 "Svc_Conf.y" +{ + ace_yyval.type_ = 1; + } +break; +case 32: +#line 200 "Svc_Conf.y" +{ + ace_yyval.type_ = 0; + } +break; +case 33: +#line 204 "Svc_Conf.y" +{ + ace_yyval.type_ = 1; + } +break; +case 34: +#line 211 "Svc_Conf.y" +{ + ace_yyval.location_node_ = new ACE_Object_Node (ace_yyvsp[-2].ident_, ace_yyvsp[0].ident_); + } +break; +case 35: +#line 215 "Svc_Conf.y" +{ + ace_yyval.location_node_ = new ACE_Function_Node (ace_yyvsp[-4].ident_, ace_yyvsp[-2].ident_); + } +break; +case 36: +#line 222 "Svc_Conf.y" +{ + ace_yyval.type_ = ACE_MODULE_T; + } +break; +case 37: +#line 226 "Svc_Conf.y" +{ + ace_yyval.type_ = ACE_SVC_OBJ_T; + } +break; +case 38: +#line 230 "Svc_Conf.y" +{ + ace_yyval.type_ = ACE_STREAM_T; + } +break; +case 40: +#line 237 "Svc_Conf.y" +{ ace_yyval.ident_ = 0; } +break; +#line 862 "y.tab.c" + } + ace_yyssp -= ace_yym; + ace_yystate = *ace_yyssp; + ace_yyvsp -= ace_yym; + ace_yym = ace_yylhs[ace_yyn]; + if (ace_yystate == 0 && ace_yym == 0) + { +#ifdef YYDEBUG + if (5 < ace_yydebug) + printf("ace_yydebug: after reduction, shifting from state 0 to\ + state %d\n", YYFINAL); +#endif + ace_yystate = YYFINAL; + *++ace_yyssp = YYFINAL; + *++ace_yyvsp = ace_yyval; + if (ace_yychar < 0) + { + if ((ace_yychar = ace_yylex()) < 0) ace_yychar = 0; +#if YYDEBUG + if (ace_yydebug) + { + ace_yys = 0; + if (ace_yychar <= YYMAXTOKEN) ace_yys = ace_yyname[ace_yychar]; + if (!ace_yys) ace_yys = "illegal-symbol"; + if (5 < ace_yydebug) + printf("ace_yydebug: state %d, reading %d (%s)\n", + YYFINAL, ace_yychar, ace_yys); + else + YYDEBUG_LOOK_AHEAD(YYFINAL, ace_yychar, ace_yys, ace_yyssp-ace_yyss); + } +#endif + } + if (ace_yychar == 0) goto ace_yyaccept; + goto ace_yyloop; + } + if ((ace_yyn = ace_yygindex[ace_yym]) && (ace_yyn += ace_yystate) >= 0 && + ace_yyn <= YYTABLESIZE && ace_yycheck[ace_yyn] == ace_yystate) + ace_yystate = ace_yytable[ace_yyn]; + else + ace_yystate = ace_yydgoto[ace_yym]; +#ifdef YYDEBUG + if (5 < ace_yydebug) + printf("ace_yydebug: after reduction, shifting from state %d \ +to state %d\n", *ace_yyssp, ace_yystate); +#endif + if (ace_yyssp >= ace_yyss + ace_yystacksize - 1) + { + goto ace_yyoverflow; + } + *++ace_yyssp = ace_yystate; + *++ace_yyvsp = ace_yyval; + goto ace_yyloop; +ace_yyoverflow: + ace_yyerror("yacc stack overflow"); +ace_yyabort: + return (1); +ace_yyaccept: + return (0); +} diff --git a/ace/Svc_Handler.cpp b/ace/Svc_Handler.cpp new file mode 100644 index 00000000000..499fb44ab56 --- /dev/null +++ b/ace/Svc_Handler.cpp @@ -0,0 +1,282 @@ +// Svc_Handler.cpp +// $Id$ + +#if !defined (ACE_SVC_HANDLER_C) +#define ACE_SVC_HANDLER_C + +#define ACE_BUILD_DLL +#include "ace/Svc_Handler.h" +#include "ace/Log_Msg.h" +#include "ace/Dynamic.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Svc_Handler.i" +#endif /* __ACE_INLINE__ */ + +#define PR_ST_1 ACE_PEER_STREAM_1 +#define PR_ST_2 ACE_PEER_STREAM_2 + +#if defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) +// Lock the creation of the Singleton. +template <PR_ST_1, ACE_SYNCH_1> +ACE_Thread_Mutex ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::ace_svc_handler_lock_; +#endif /* defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ + +template <PR_ST_1, ACE_SYNCH_1> ACE_Dynamic * +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::instance (void) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::allocated"); + +#if defined (ACE_MT_SAFE) && defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + // Lock the creation of the Singleton. This should be inside of + // ACE_Svc_Handler, but GNU G++ is too lame to handle this... + static ACE_Thread_Mutex ace_svc_handler_lock_; +#endif /* defined (ACE_MT_SAFE) && defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ + + static ACE_TSS_TYPE (ACE_Dynamic) *instance_; + // Determines if we were dynamically allocated. Note that this + // should be inside of ACE_Svc_Handler, but G++ is too lame to + // support this... + + // Implement the Double Check pattern. + + if (instance_ == 0) + { + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ace_svc_handler_lock_, 0)); + + if (instance_ == 0) + ACE_NEW_RETURN (instance_, ACE_TSS_TYPE (ACE_Dynamic), 0); + } + + return ACE_TSS_GET (instance_, ACE_Dynamic); +} + +template <PR_ST_1, ACE_SYNCH_1> void * +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::operator new (size_t n) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::operator new"); + // Allocate the memory and store it (usually in thread-specific + // storage, depending on config flags). + return ACE_Svc_Handler<ACE_PEER_STREAM_2, ACE_SYNCH_2>::instance ()->set (::new char[n]); +} + +template <PR_ST_1, ACE_SYNCH_1> void +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::destroy (void) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::destroy"); + + // Only delete ourselves if we've been allocated dynamically. + if (this->dynamic_) + // Will call the destructor, which automatically calls <shutdown>. + // Note that if we are *not* allocated dynamically then the + // destructor will call <shutdown> automatically when it gets run + // during cleanup. + delete this; +} + +template <PR_ST_1, ACE_SYNCH_1> void +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::operator delete (void *obj) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::delete"); + ::delete obj; +} + +/* Default constructor */ + +template <PR_ST_1, ACE_SYNCH_1> +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::ACE_Svc_Handler (ACE_Thread_Manager *tm, + ACE_Message_Queue<ACE_SYNCH_2> *mq, + ACE_Reactor *reactor) + : ACE_Task<ACE_SYNCH_2> (tm, mq), + reactor_ (reactor) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::ACE_Svc_Handler"); + + // This clever idiom transparently checks if we were allocated + // dynamically. This information is used by the <destroy> method to + // decide if we need to delete <this>... The idiom is based on a + // paper by Michael van Rooyen (mrooyen@cellnet.co.uk) that appeared + // in the April '96 issue of the C++ Report. We've spruced it up to + // work correctly in multi-threaded programs by using our ACE_TSS + // class. + this->dynamic_ = ACE_Svc_Handler<ACE_PEER_STREAM_2, ACE_SYNCH_2>::instance()->is_dynamic (this); +} + +// Default behavior for a ACE_Svc_Handler object is to be registered with +// the ACE_Reactor (thereby ensuring single threading). + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::open (void *) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::open"); +#if defined (DEBUGGING) + char buf[BUFSIZ]; + ACE_PEER_STREAM_ADDR client_addr; + + if (this->peer_.get_remote_addr (client_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "get_remote_addr"), -1); + + if (client_addr.addr_to_string (buf, sizeof buf) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", + "can't obtain peer's address"), -1); + + ACE_DEBUG ((LM_DEBUG, "connected to %s on fd %d\n", + buf, this->peer_.get_handle ())); +#endif /* DEBUGGING */ + if (this->reactor_ + && this->reactor_->register_handler (this, + ACE_Event_Handler::READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p", + "unable to register client handler"), -1); + return 0; +} + +// Perform termination activities. + +template <PR_ST_1, ACE_SYNCH_1> void +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::shutdown (void) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::shutdown"); + // Deregister this handler with the ACE_Reactor. + if (this->reactor_) + { + ACE_Reactor_Mask mask = ACE_Event_Handler::WRITE_MASK | + ACE_Event_Handler::READ_MASK | + ACE_Event_Handler::DONT_CALL; + + // Remove self from reactor. + this->reactor_->remove_handler (this, mask); + + // Make sure there are no timers. + this->reactor_->cancel_timer( this ); + + // Note the fact that the Reactor has shut down. + this->reactor_ = 0; + } + + this->peer ().close (); +} + +template <PR_ST_1, ACE_SYNCH_1> ACE_Reactor * +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::reactor (void) const +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::reactor"); + return this->reactor_; +} + +template <PR_ST_1, ACE_SYNCH_1> void +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::reactor (ACE_Reactor *r) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::reactor"); + this->reactor_ = r; +} + +template <PR_ST_1, ACE_SYNCH_1> void +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::dump"); +} + +template <PR_ST_1, ACE_SYNCH_1> ACE_INLINE ACE_PEER_STREAM & +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::peer (void) const +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::peer"); + return (PEER_STREAM &) this->peer_; +} + +// Extract the underlying PEER_STREAM (e.g., used by ACE_Connector and +// ACE_Acceptor). + +template <PR_ST_1, ACE_SYNCH_1> +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::operator ACE_PEER_STREAM &() +{ + return this->peer_; +} + +/* Extract the underlying I/O descriptor. */ + +template <PR_ST_1, ACE_SYNCH_1> ACE_HANDLE +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::get_handle (void) const +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::get_handle"); + return this->peer_.get_handle (); +} + +/* Set the underlying I/O descriptor. */ + +template <PR_ST_1, ACE_SYNCH_1> void +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::set_handle (ACE_HANDLE h) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::set_handle"); + this->peer_.set_handle (h); +} + +template <PR_ST_1, ACE_SYNCH_1> +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::~ACE_Svc_Handler (void) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::~ACE_Svc_Handler"); + this->shutdown (); +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::handle_close (ACE_HANDLE, ACE_Reactor_Mask) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::handle_close"); + + this->destroy (); + return 0; +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::handle_timeout (const ACE_Time_Value &, + const void *) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::handle_timeout"); + return this->handle_close (); +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::close (unsigned long) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::close"); + return this->handle_close (); +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::svc (void) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::svc"); + return -1; +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::put (ACE_Message_Block *, + ACE_Time_Value *) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::put"); + return -1; +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::init (int, char *[]) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::init"); + return -1; +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::fini (void) +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::fini"); + return -1; +} + +template <PR_ST_1, ACE_SYNCH_1> int +ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::info (char **, size_t) const +{ + ACE_TRACE ("ACE_Svc_Handler<PR_ST_2, ACE_SYNCH_2>::info"); + return -1; +} +#undef PR_ST_1 +#undef PR_ST_2 +#endif /* ACE_SVC_HANDLER_C */ diff --git a/ace/Svc_Handler.h b/ace/Svc_Handler.h new file mode 100644 index 00000000000..2862d1f2ad0 --- /dev/null +++ b/ace/Svc_Handler.h @@ -0,0 +1,178 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Svc_Handler.h +// +// = AUTHOR +// Doug Schmidt and Irfan Pyrarli. +// +// ============================================================================ + +#if !defined (ACE_SVC_HANDLER_H) +#define ACE_SVC_HANDLER_H + +#include "ace/Synch_Options.h" +#include "ace/Task.h" +#include "ace/Service_Config.h" +#include "ace/Synch_T.h" + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +#define ACE_PEER_STREAM_1 class PEER_STREAM +#define ACE_PEER_STREAM_2 PEER_STREAM +#define ACE_PEER_STREAM PEER_STREAM +#define ACE_PEER_STREAM_ADDR PEER_STREAM::PEER_ADDR +#else +#define ACE_PEER_STREAM_1 class PEER_STREAM, class PEER_ADDR +#define ACE_PEER_STREAM_2 PEER_STREAM, PEER_ADDR +#define ACE_PEER_STREAM PEER_STREAM +#define ACE_PEER_STREAM_ADDR PEER_ADDR +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +// Forward decls. +class ACE_Dynamic; + +template <ACE_PEER_STREAM_1, ACE_SYNCH_1> +class ACE_Svc_Handler : public ACE_Task<ACE_SYNCH_2> + // = TITLE + // Defines the interface for a service that exchanges data with + // its connected peer. + // + // = DESCRIPTION + // This class provides a well-defined interface that the + // Acceptor and Connector pattern factories use as their target. + // Typically, client applications will subclass ACE_Svc_Handler + // and do all the interesting work in the subclass. One thing + // that the ACE_Svc_Handler does contain is a PEER_STREAM + // endpoint that is initialized by an ACE_Acceptor or + // ACE_Connector when a connection is established successfully. + // This endpoint is used to exchange data between a + // ACE_Svc_Handler and the peer it is connected with. +{ +public: + // = Initialization and termination methods. + ACE_Svc_Handler (ACE_Thread_Manager * = 0, + ACE_Message_Queue<ACE_SYNCH_2> * = 0, + ACE_Reactor * = ACE_Service_Config::reactor ()); + + virtual ~ACE_Svc_Handler (void); + + virtual int open (void * = 0); + // Activate the client handler (called by the ACE_Acceptor or + // ACE_Connector). + + virtual int close (u_long flags = 0); + // Object termination hook. + + // = Dynamic linking hooks. + virtual int init (int argc, char *argv[]); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int fini (void); + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + virtual int info (char **info_string, size_t length) const; + // Default version does no work and returns -1. Must be overloaded + // by application developer to do anything meaningful. + + // = Demultiplexing hooks. + + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::RWE_MASK); + // Perform termination activities on the SVC_HANDLER. The default + // behavior is to close down the <peer_> (to avoid descriptor leaks) + // and to delete this (to avoid memory leaks)! If you don't want + // this behavior make sure you override this method... + + virtual int handle_timeout (const ACE_Time_Value &time, + const void *); + // Default behavior when timeouts occur is to close down the + // <Svc_Handler> by calling <handle_close>. + + virtual ACE_HANDLE get_handle (void) const; + // Get the underlying handle associated with the <peer_>. + + virtual void set_handle (ACE_HANDLE); + // Set the underlying handle associated with the <peer_>. + + ACE_PEER_STREAM &peer (void) const; + // Returns the underlying PEER_STREAM + + operator ACE_PEER_STREAM &(); + // Returns the underlying PEER_STREAM (used by + // ACE_Acceptor::accept() and ACE_Connector::connect() factories). + + virtual int put (ACE_Message_Block *, ACE_Time_Value *tv = 0); + // Provide a default implementation to simplify ancestors... + + ACE_Reactor *reactor (void) const; + // Get the underlying Reactor *. + + void reactor (ACE_Reactor *); + // Set the underlying Reactor *. + + virtual void destroy (void); + // Call this instead of <delete> to free up dynamically allocated + // <Svc_Handler>. This method knows whether or not the object was + // allocated dynamically, and can act accordingly (i.e., deleting it + // if it was allocated dynamically, otherwise ignoring it). + + void *operator new (size_t n); + // Overloaded new operator. This is used to unobtrusively detect + // when a Svc_Handler is allocated dynamically. + + void dump (void) const; + // Dump the state of an object. + +public: + + void operator delete (void *); + // This really should be private so that users are forced to call + // destroy(). + + virtual int svc (void); + // Provide a default implementation to simplify ancestors... + +private: + void shutdown (void); + // Close down the descriptor + + ACE_PEER_STREAM peer_; + // Maintain connection with client. + + ACE_Reactor *reactor_; + // Event demultiplex associated with this object. + + static ACE_Dynamic *instance (void); + // Point of access to the singleton. + + char dynamic_; + // Have we been dynamically created? + +#if defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + static ACE_Thread_Mutex ace_svc_handler_lock_; + // Lock the creation of the Singleton. +#endif /* defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ +}; + +#if defined (__ACE_INLINE__) +#include "ace/Svc_Handler.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Svc_Handler.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Svc_Handler.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_SVC_HANDLER_H */ diff --git a/ace/Svc_Handler.i b/ace/Svc_Handler.i new file mode 100644 index 00000000000..f138a9fd2b7 --- /dev/null +++ b/ace/Svc_Handler.i @@ -0,0 +1,5 @@ +/* -*- C++ -*- */ +// $Id$ + +// Svc_Handler.i + diff --git a/ace/Synch.cpp b/ace/Synch.cpp new file mode 100644 index 00000000000..7201a4bb933 --- /dev/null +++ b/ace/Synch.cpp @@ -0,0 +1,839 @@ +// Synch.cpp +// $Id$ + +#if !defined (ACE_SYNCH_C) +#define ACE_SYNCH_C + +#define ACE_BUILD_DLL +#include "ace/Thread.h" +#include "ace/Synch.h" +#include "ace/Log_Msg.h" +#include "ace/Time_Value.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Synch.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Null_Mutex) +ACE_ALLOC_HOOK_DEFINE(ACE_File_Lock) +ACE_ALLOC_HOOK_DEFINE(ACE_RW_Process_Mutex) + +ACE_ALLOC_HOOK_DEFINE(ACE_Process_Mutex) + +void +ACE_Process_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_Process_Mutex::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Process_Mutex::ACE_Process_Mutex (LPCTSTR name, void *arg) +#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) + : lock_ (USYNC_PROCESS, name, arg) +#else + : lock_ (name) +#endif /* ACE_WIN32 || ACE_HAS_POSIX_SEM */ +{ +// ACE_TRACE ("ACE_Process_Mutex::ACE_Process_Mutex"); +} + +ACE_Process_Mutex::~ACE_Process_Mutex (void) +{ +} + +// Explicitly destroy the mutex. +int +ACE_Process_Mutex::remove (void) +{ + return this->lock_.remove (); +} + +// Acquire lock ownership (wait on priority queue if necessary). +int +ACE_Process_Mutex::acquire (void) +{ + return this->lock_.acquire (); +} + +// Conditionally acquire lock (i.e., don't wait on queue). +int +ACE_Process_Mutex::tryacquire (void) +{ + return this->lock_.tryacquire (); +} + +// Release lock and unblock a thread at head of priority queue. +int +ACE_Process_Mutex::release (void) +{ + return this->lock_.release (); +} + +// Acquire lock ownership (wait on priority queue if necessary). +int +ACE_Process_Mutex::acquire_read (void) +{ + return this->lock_.acquire_read (); +} + +// Acquire lock ownership (wait on priority queue if necessary). +int ACE_Process_Mutex::acquire_write (void) +{ + return this->lock_.acquire_write (); +} + +// Conditionally acquire a lock (i.e., won't block). +int +ACE_Process_Mutex::tryacquire_read (void) +{ + return this->lock_.tryacquire_read (); +} + +// Conditionally acquire a lock (i.e., won't block). +int +ACE_Process_Mutex::tryacquire_write (void) +{ + return this->lock_.tryacquire_write (); +} + +ACE_RW_Process_Mutex::ACE_RW_Process_Mutex (LPCTSTR name, + void *arg) + : ACE_Process_Mutex (name, arg) +{ +// ACE_TRACE ("ACE_RW_Process_Mutex::ACE_RW_Process_Mutex"); +} + +void +ACE_RW_Process_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_RW_Process_Mutex::dump"); + ACE_Process_Mutex::dump (); +} + +void +ACE_File_Lock::dump (void) const +{ +// ACE_TRACE ("ACE_File_Lock::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_File_Lock::ACE_File_Lock (ACE_HANDLE h) +{ +// ACE_TRACE ("ACE_File_Lock::ACE_File_Lock"); + if (ACE_OS::flock_init (&this->lock_) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_File_Lock::ACE_File_Lock")); + this->set_handle (h); +} + +ACE_File_Lock::ACE_File_Lock (const char *name, + int flags, + mode_t perms) +{ +// ACE_TRACE ("ACE_File_Lock::ACE_File_Lock"); + + if (ACE_OS::flock_init (&this->lock_, flags, name, perms) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_File_Lock::ACE_File_Lock")); +} + +ACE_File_Lock::~ACE_File_Lock (void) +{ +// ACE_TRACE ("ACE_File_Lock::~ACE_File_Lock"); + if (this->remove () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_File_Lock::~ACE_File_Lock")); +} + +#if defined (ACE_HAS_THREADS) + +ACE_Event::ACE_Event (int manual_reset, + int initial_state, + int type, + LPCTSTR name, + void *arg) +{ + if (ACE_OS::event_init (&this->handle_, + manual_reset, + initial_state, + type, + name, + arg) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Event::ACE_Event")); +} + +ACE_Event::~ACE_Event (void) +{ + if (this->remove () != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Event::~ACE_Event")); +} + +int +ACE_Event::remove (void) +{ + return ACE_OS::event_destroy (&this->handle_); +} + +ACE_event_t +ACE_Event::handle (void) const +{ + return this->handle_; +} + +int +ACE_Event::wait (void) +{ + return ACE_OS::event_wait (&this->handle_); +} + +int +ACE_Event::wait (const ACE_Time_Value *abstime) +{ + return ACE_OS::event_timedwait (&this->handle_, + (ACE_Time_Value *) abstime); +} + +int +ACE_Event::signal (void) +{ + return ACE_OS::event_signal (&this->handle_); +} + +int +ACE_Event::pulse (void) +{ + return ACE_OS::event_pulse (&this->handle_); +} + +int +ACE_Event::reset (void) +{ + return ACE_OS::event_reset (&this->handle_); +} + +void +ACE_Event::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Manual_Event::ACE_Manual_Event (int initial_state, + int type, + LPCTSTR name, + void *arg) + : ACE_Event (1, + initial_state, + type, + name, + arg) +{ +} + +void +ACE_Manual_Event::dump (void) const +{ + ACE_Event::dump (); +} + +ACE_Auto_Event::ACE_Auto_Event (int initial_state, + int type, + LPCTSTR name, + void *arg) + : ACE_Event (0, + initial_state, + type, + name, + arg) +{ +} + +void +ACE_Auto_Event::dump (void) const +{ + ACE_Event::dump (); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Recursive_Thread_Mutex) +ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Mutex_Guard) +ACE_ALLOC_HOOK_DEFINE(ACE_Mutex) +ACE_ALLOC_HOOK_DEFINE(ACE_Semaphore) + +void +ACE_Semaphore::dump (void) const +{ +// ACE_TRACE ("ACE_Semaphore::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Thread_Semaphore::dump (void) const +{ +// ACE_TRACE ("ACE_Thread_Semaphore::dump"); + + ACE_Semaphore::dump (); +} + +ACE_Semaphore::ACE_Semaphore (u_int count, + int type, + LPCTSTR name, + void *arg, + int max) +{ +// ACE_TRACE ("ACE_Semaphore::ACE_Semaphore"); + if (ACE_OS::sema_init (&this->semaphore_, count, type, + name, arg, max) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Semaphore::ACE_Semaphore")); +} + +ACE_Thread_Semaphore::ACE_Thread_Semaphore (u_int count, + LPCTSTR name, + void *arg, + int max) + : ACE_Semaphore (count, USYNC_THREAD, name, arg, max) +{ +// ACE_TRACE ("ACE_Thread_Semaphore::ACE_Thread_Semaphore"); +} + +void +ACE_Process_Semaphore::dump (void) const +{ +// ACE_TRACE ("ACE_Process_Semaphore::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Process_Semaphore::ACE_Process_Semaphore (u_int count, + LPCTSTR name, + void *arg, + int max) +#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) + : lock_ (count, USYNC_PROCESS, name, arg, max) +#else + : lock_ (name, ACE_SV_Semaphore_Complex::ACE_CREATE, count) +#endif /* ACE_WIN32 || ACE_HAS_POSIX_SEM */ +{ +// ACE_TRACE ("ACE_Process_Semaphore::ACE_Process_Semaphore"); +} + +ACE_Process_Semaphore::~ACE_Process_Semaphore (void) +{ +// ACE_TRACE ("ACE_Process_Semaphore::~ACE_Process_Semaphore"); +} + +// Explicitly destroy the semaphore. + +int +ACE_Process_Semaphore::remove (void) +{ +// ACE_TRACE ("ACE_Process_Semaphore::remove"); + return this->lock_.remove (); +} + +// Block the thread until the semaphore count becomes +// greater than 0, then decrement it. + +int +ACE_Process_Semaphore::acquire (void) +{ +// ACE_TRACE ("ACE_Process_Semaphore::acquire"); + return this->lock_.acquire (); +} + +// Conditionally decrement the semaphore if count is greater +// than 0 (i.e., won't block). + +int +ACE_Process_Semaphore::tryacquire (void) +{ +// ACE_TRACE ("ACE_Process_Semaphore::tryacquire"); + return this->lock_.tryacquire (); +} + +// Increment the semaphore, potentially unblocking +// a waiting thread. + +int +ACE_Process_Semaphore::release (void) +{ +// ACE_TRACE ("ACE_Process_Semaphore::release"); + return this->lock_.release (); +} + +ACE_Semaphore::~ACE_Semaphore (void) +{ +// ACE_TRACE ("ACE_Semaphore::~ACE_Semaphore"); + this->remove (); +} + +void +ACE_Thread_Mutex_Guard::dump (void) const +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_Mutex::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Mutex::ACE_Mutex (int type, LPCTSTR name, void *arg) +{ +// ACE_TRACE ("ACE_Mutex::ACE_Mutex"); + + if (ACE_OS::mutex_init (&this->lock_, type, name, arg) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Mutex::ACE_Mutex")); +} + +ACE_Mutex::~ACE_Mutex (void) +{ +// ACE_TRACE ("ACE_Mutex::~ACE_Mutex"); + if (this->remove () != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Mutex::~ACE_Mutex")); +} + +ACE_thread_t +ACE_Recursive_Thread_Mutex::get_thread_id (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::get_thread_id"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->nesting_mutex_, ACE_OS::NULL_thread); + return this->owner_id_; +} + +int +ACE_Recursive_Thread_Mutex::get_nesting_level (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::get_nesting_level"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->nesting_mutex_, -1); + return this->nesting_level_; +} + +ACE_Recursive_Thread_Mutex::ACE_Recursive_Thread_Mutex (const ACE_Recursive_Thread_Mutex &rm) + : lock_available_ ((ACE_Thread_Mutex &) rm.nesting_mutex_) +{ +} + +ACE_Recursive_Thread_Mutex::ACE_Recursive_Thread_Mutex (LPCTSTR name, + void *arg) + : nesting_level_ (0), + owner_id_ (ACE_OS::NULL_thread), + nesting_mutex_ (name, arg), + lock_available_ (nesting_mutex_, name, arg) +{ +#if defined (ACE_HAS_FSU_PTHREADS) +// Initialize FSU pthreads package. +// If called more than once, pthread_init does nothing +// and so does no harm. + pthread_init (); +#endif // ACE_HAS_FSU_PTHREADS +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::ACE_Recursive_Thread_Mutex"); +} + +ACE_Recursive_Thread_Mutex::~ACE_Recursive_Thread_Mutex (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::~ACE_Recursive_Thread_Mutex"); +} + +int +ACE_Recursive_Thread_Mutex::acquire (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::acquire"); + ACE_thread_t t_id = ACE_Thread::self (); + + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->nesting_mutex_, -1); + + // If there's no contention, just grab the lock immediately. + if (this->nesting_level_ == 0) + { + this->set_thread_id (t_id); + this->nesting_level_ = 1; + } + // If we already own the lock, then increment the nesting level and + // proceed. + else if (ACE_OS::thr_equal (t_id, this->owner_id_)) + this->nesting_level_++; + else + { + // Wait until the nesting level has dropped to zero, + // at which point we can acquire the lock. + while (this->nesting_level_ > 0) + this->lock_available_.wait (); + + // Note that at this point the nesting_mutex_ is held... + + this->set_thread_id (t_id); + this->nesting_level_ = 1; + } + + return 0; +} + +int +ACE_Recursive_Thread_Mutex::release (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::release"); + ACE_thread_t t_id = ACE_Thread::self (); + + // Automatically acquire mutex. + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->nesting_mutex_, -1); + +#if !defined (ACE_NDEBUG) + if (this->nesting_level_ == 0 + || ACE_OS::thr_equal (t_id, this->owner_id_) == 0) + { + errno = EINVAL; + ACE_RETURN (-1); + } +#endif /* ACE_NDEBUG */ + + this->nesting_level_--; + if (this->nesting_level_ == 0) + { + // This may not be strictly necessary, but it does put the mutex + // into a known state... + this->set_thread_id (ACE_OS::NULL_thread); + + // Inform waiters that the lock is free. + this->lock_available_.signal (); + } + return 0; +} + +int +ACE_Recursive_Thread_Mutex::tryacquire (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::tryacquire"); + ACE_thread_t t_id = ACE_Thread::self (); + + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->nesting_mutex_, -1); + + // If there's no contention, just grab the lock immediately. + if (this->nesting_level_ == 0) + { + this->set_thread_id (t_id); + this->nesting_level_ = 1; + } + // If we already own the lock, then increment the nesting level and + // proceed. + else if (ACE_OS::thr_equal (t_id, this->owner_id_)) + this->nesting_level_++; + else + { + errno = EBUSY; + ACE_RETURN (-1); + } + return 0; +} + +void +ACE_Recursive_Thread_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->lock_available_.dump (); + this->nesting_mutex_.dump (); + ACE_DEBUG ((LM_DEBUG, "nesting_level_ = %d", this->nesting_level_)); +#if !defined (ACE_HAS_DCETHREADS) && !defined (ACE_HAS_PTHREADS) + ACE_DEBUG ((LM_DEBUG, "\nowner_id_ = %u", this->owner_id_)); +#else + ACE_DEBUG ((LM_DEBUG, "\n")); +#endif /* !ACE_HAS_DCETHREADS */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Condition_Thread_Mutex) + +void +ACE_Condition_Thread_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); +#if defined (ACE_WIN32) + ACE_DEBUG ((LM_DEBUG, + "waiters = %d\n", + this->cond_.waiters_)); +#endif /* ACE_WIN32 */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex (const ACE_Thread_Mutex &m, + LPCTSTR name, + void *arg) + : mutex_ ((ACE_Thread_Mutex &) m) +{ +#if defined (ACE_HAS_FSU_PTHREADS) +// Initialize FSU pthreads package. +// If called more than once, pthread_init does nothing +// and so does no harm. + pthread_init (); +#endif // ACE_HAS_FSU_PTHREADS + +// ACE_TRACE ("ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex"); + if (ACE_OS::cond_init (&this->cond_, USYNC_THREAD, name, arg) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", + "ACE_Condition_Thread_Mutex::ACE_Condition_Thread_Mutex")); +} + +ACE_Condition_Thread_Mutex::~ACE_Condition_Thread_Mutex (void) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::~ACE_Condition_Thread_Mutex"); + if (this->remove () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Condition_Thread_Mutex::~ACE_Condition_Thread_Mutex")); +} + +// Peform an "alertable" timed wait. If the argument <abstime> == 0 +// then we do a regular <cond_wait>, else we do a timed wait for up to +// <abstime> using the <cond_timedwait> function. + +int +ACE_Condition_Thread_Mutex::wait (void) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait"); + ACE_thread_mutex_t &mutex = (ACE_thread_mutex_t &) this->mutex_.lock (); + + return ACE_OS::cond_wait (&this->cond_, &mutex); +} + +int +ACE_Condition_Thread_Mutex::wait (ACE_Thread_Mutex &mutex, + const ACE_Time_Value *abstime) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::wait"); + if (abstime == 0) + return this->wait (); + else + return ACE_OS::cond_timedwait (&this->cond_, + &mutex.lock_, + (ACE_Time_Value *) abstime); +} + +int +ACE_Condition_Thread_Mutex::wait (const ACE_Time_Value *abstime) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait"); + if (abstime == 0) + return this->wait (); + else + return this->wait (this->mutex_, abstime); +} + +int +ACE_Condition_Thread_Mutex::signal (void) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::signal"); + return ACE_OS::cond_signal (&this->cond_); +} + +int +ACE_Condition_Thread_Mutex::broadcast (void) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::broadcast"); + return ACE_OS::cond_broadcast (&this->cond_); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Sub_Barrier) + +void +ACE_Sub_Barrier::dump (void) const +{ +// ACE_TRACE ("ACE_Sub_Barrier::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->barrier_finished_.dump (); + ACE_DEBUG ((LM_DEBUG, "running_threads_ = %d", this->running_threads_)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Sub_Barrier::ACE_Sub_Barrier (u_int count, + ACE_Thread_Mutex &lock, + LPCTSTR name, + void *arg) + : barrier_finished_ (lock, name, arg), + running_threads_ (count) +{ +// ACE_TRACE ("ACE_Sub_Barrier::ACE_Sub_Barrier"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Barrier) +ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Barrier) +ACE_ALLOC_HOOK_DEFINE(ACE_Process_Barrier) + +void +ACE_Barrier::dump (void) const +{ +// ACE_TRACE ("ACE_Barrier::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, "current_generation_ = %d", this->current_generation_)); + ACE_DEBUG ((LM_DEBUG, "\ncount_ = %d", this->count_)); + this->sub_barrier_1_.dump (); + this->sub_barrier_2_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Barrier::ACE_Barrier (u_int count, + LPCTSTR name, + void *arg) + : lock_ (name, arg), + current_generation_ (0), + count_ (count), + sub_barrier_1_ (count, lock_, name, arg), + sub_barrier_2_ (count, lock_, name, arg) +{ +// ACE_TRACE ("ACE_Barrier::ACE_Barrier"); + this->sub_barrier_[0] = &this->sub_barrier_1_; + this->sub_barrier_[1] = &this->sub_barrier_2_; +} + +int +ACE_Barrier::wait (void) +{ +// ACE_TRACE ("ACE_Barrier::wait"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + ACE_Sub_Barrier *sbp = + this->sub_barrier_[this->current_generation_]; + + // Check for shutdown... + if (sbp == 0) + return -1; + + if (sbp->running_threads_ == 1) + { + // We're the last running thread, so swap generations and tell + // all the threads waiting on the barrier to continue on their + // way. + + sbp->running_threads_ = this->count_; + // Swap generations. + this->current_generation_ = 1 - this->current_generation_; + sbp->barrier_finished_.broadcast (); + } + else + { + --sbp->running_threads_; + + // Block until all the other threads wait(). + while (sbp->running_threads_ != this->count_) + sbp->barrier_finished_.wait (); + } + + return 0; +} + +ACE_Thread_Barrier::ACE_Thread_Barrier (u_int count, LPCTSTR name) + : ACE_Barrier (count, name) +{ +// ACE_TRACE ("ACE_Thread_Barrier::ACE_Thread_Barrier"); +} + +void +ACE_Thread_Barrier::dump (void) const +{ +// ACE_TRACE ("ACE_Thread_Barrier::dump"); + ACE_Barrier::dump (); +} + +#if 0 +ACE_Process_Barrier::ACE_Process_Barrier (u_int count, LPCTSTR name) + : ACE_Barrier (count, USYNC_PROCESS, name) +{ +// ACE_TRACE ("ACE_Process_Barrier::ACE_Process_Barrier"); +} + +void +ACE_Process_Barrier::dump (void) const +{ +// ACE_TRACE ("ACE_Process_Barrier::dump"); + ACE_Barrier::dump (); +} + +#endif /* 0 */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Mutex) + +void +ACE_Thread_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_Thread_Mutex::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_Thread_Mutex::~ACE_Thread_Mutex (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::~ACE_Thread_Mutex"); +} + +ACE_Thread_Mutex::ACE_Thread_Mutex (LPCTSTR name, void *arg) +{ +// ACE_TRACE ("ACE_Thread_Mutex::ACE_Thread_Mutex"); + + if (ACE_OS::thread_mutex_init (&this->lock_, USYNC_THREAD, name, arg) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Mutex::ACE_Mutex")); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_RW_Thread_Mutex) + +ACE_RW_Thread_Mutex::ACE_RW_Thread_Mutex (LPCTSTR name, + void *arg) + : ACE_RW_Mutex (USYNC_THREAD, name, arg) +{ +// ACE_TRACE ("ACE_RW_Thread_Mutex::ACE_RW_Thread_Mutex"); +} + +void +ACE_RW_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_RW_Mutex::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_RW_Thread_Mutex::dump (void) const +{ +// ACE_TRACE ("ACE_RW_Thread_Mutex::dump"); + ACE_RW_Mutex::dump (); +} + +ACE_RW_Mutex::ACE_RW_Mutex (int type, LPCTSTR name, void *arg) +{ +// ACE_TRACE ("ACE_RW_Mutex::ACE_RW_Mutex"); + if (ACE_OS::rwlock_init (&this->lock_, type, name, arg) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_RW_Mutex::~ACE_RW_Mutex")); +} + +ACE_RW_Mutex::~ACE_RW_Mutex (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::~ACE_RW_Mutex"); + if (this->remove () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_RW_Mutex::~ACE_RW_Mutex")); +} + +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_SYNCH_C */ diff --git a/ace/Synch.h b/ace/Synch.h new file mode 100644 index 00000000000..01f33cd8748 --- /dev/null +++ b/ace/Synch.h @@ -0,0 +1,1019 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Synch.h +// +// = DESCRIPTION +// Wrappers for various synchronization routines. +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SYNCH_H) +#define ACE_SYNCH_H + +#include "ace/ACE.h" +#include "ace/SV_Semaphore_Complex.h" + +// Forward declarations. +class ACE_Time_Value; +// template <class ACE_COND_MUTEX> class ACE_Condition; + +class ACE_Export ACE_File_Lock + // = TITLE + // A wrapper around the UNIX file locking mechanism. + // + // = DESCRIPTION + // Allows us to "adapt" the UNIX file locking mechanisms to work + // with all of our Guard stuff... +{ +public: + ACE_File_Lock (ACE_HANDLE handle = ACE_INVALID_HANDLE); + // Set the <handle_> of the File_Lock to <handle>. Note that this + // constructor assumes ownership of the <handle> and will close it + // down in <remove>. If you want the <handle> stays open when + // <remove> is called make sure to call <dup> on the <handle> before + // closing it. + + ACE_File_Lock (const char *filename, int flags, mode_t mode = 0); + // Open the <filename> with <flags> and <mode> and set the result to + // <handle_>. + + ~ACE_File_Lock (void); + // Remove a File lock by releasing it and closing down the <handle_>. + + int remove (void); + // Remove a File lock by releasing it and closing down the <handle_>. + + int acquire (short whence = 0, off_t start = 0, off_t len = 1); + // Note, for interface uniformity with other synchronization + // wrappers we include the <acquire> method. This is implemented as + // a write-lock to be on the safe-side... + + int tryacquire (short whence = 0, off_t start = 0, off_t len = 1); + // Note, for interface uniformity with other synchronization + // wrappers we include the <tryacquire> method. This is implemented + // as a write-lock to be on the safe-side... + + int release (short whence = 0, off_t start = 0, off_t len = 1); + // Unlock a readers/writer lock. + + int acquire_write (short whence = 0, off_t start = 0, off_t len = 1); + // Acquire a write lock, but block if any readers or a + // writer hold the lock. + + int tryacquire_write (short whence = 0, off_t start = 0, off_t len = 1); + // Conditionally acquire a write lock (i.e., won't block). + + int acquire_read (short whence = 0, off_t start = 0, off_t len = 1); + // Acquire a read lock, but block if a writer hold the lock. + + int tryacquire_read (short whence = 0, off_t start = 0, off_t len = 1); + // Conditionally acquire a read lock (i.e., won't block). + + ACE_HANDLE get_handle (void); + // Get underlying <ACE_HANDLE>. + + void set_handle (ACE_HANDLE); + // Set underlying <ACE_HANDLE>. Note that this method assumes + // ownership of the <handle> and will close it down in <remove>. If + // you want the <handle> stays open when <remove> is called make + // sure to call <dup> on the <handle> before closing it. + + void dump (void) const; + // Dump state of the object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_OS::flock_t lock_; + // Locking structure for OS record locks. + + // = Prevent assignment and initialization. + void operator= (const ACE_File_Lock &) {} + ACE_File_Lock (const ACE_File_Lock &) {} +}; + +#if defined (ACE_HAS_THREADS) // ACE platform supports some form of threading. + +class ACE_Export ACE_Event + // = TITLE + // A wrapper around the Win32 event locking mechanism. + // + // = DESCRIPTION + // Portable implementation of an Event mechanism, which is + // native to Win32, but must be emulated on UNIX. +{ +public: + ACE_Event (int manual_reset = 0, + int initial_state = 0, + int type = USYNC_THREAD, + LPCTSTR name = 0, + void *arg = 0); + // Constructor which will create event. + + ~ACE_Event (void); + // Implicitly destroy the event variable. + + int remove (void); + // Explicitly destroy the event variable. + + ACE_event_t handle (void) const; + // Underlying handle to event. + + int wait (void); + // if MANUAL reset + // sleep till the event becomes signaled + // event remains signaled after wait() completes. + // else AUTO reset + // sleep till the event becomes signaled + // event resets wait() completes. + + int wait (const ACE_Time_Value *abstime); + // Same as wait() above, but this one can be timed + // <abstime> is absolute time-of-day. + + int signal (void); + // if MANUAL reset + // wake up all waiting threads + // set to signaled state + // else AUTO reset + // if no thread is waiting, set to signaled state + // if thread(s) are waiting, wake up one waiting thread and + // reset event + + int pulse (void); + // if MANUAL reset + // wakeup all waiting threads and + // reset event + // else AUTO reset + // wakeup one waiting thread (if present) and + // reset event + + int reset (void); + // Set to nonsignaled state. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks + +private: + + // prevent copy constructors + ACE_Event (const ACE_Event& event); + + // prevent assignment operators + const ACE_Event &operator= (const ACE_Event &rhs); + + ACE_event_t handle_; +}; + +class ACE_Export ACE_Manual_Event : public ACE_Event + // = TITLE + // Manual Events. + // + // = DESCRIPTION + // Specialization of Event mechanism which + // wakes up all on signal() +{ +public: + ACE_Manual_Event (int initial_state = 0, + int type = USYNC_THREAD, + LPCTSTR name = 0, + void *arg = 0); + // constructor which will create manual event + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks +}; + +class ACE_Export ACE_Auto_Event : public ACE_Event + // = TITLE + // Auto Events. + // + // = DESCRIPTION + // Specialization of Event mechanism which + // wakes up all on signal() +{ +public: + ACE_Auto_Event (int initial_state = 0, + int type = USYNC_THREAD, + LPCTSTR name = 0, + void *arg = 0); + // constructor which will create auto event + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks +}; + +class ACE_Export ACE_Mutex + // = TITLE + // ACE_Mutex wrapper (valid in same process or across processes + // (depending on TYPE flag)) +{ +public: + ACE_Mutex (int type = USYNC_THREAD, + LPCTSTR name = 0, + void *arg = 0); + // Initialize the mutex. + + ~ACE_Mutex (void); + // Implicitly destroy the mutex. + + int remove (void); + // Explicitly destroy the mutex. + + int acquire (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int tryacquire (void); + // Conditionally acquire lock (i.e., don't wait on queue). + + int release (void); + // Release lock and unblock a thread at head of priority queue. + + int acquire_read (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int acquire_write (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int tryacquire_read (void); + // Conditionally acquire a lock (i.e., won't block). + + int tryacquire_write (void); + // Conditionally acquire a lock (i.e., won't block). + + const ACE_mutex_t &lock (void) const; + // Return the underlying mutex. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +//private: + ACE_mutex_t lock_; + // Mutex type supported by the OS. + +private: + // = Prevent assignment and initialization. + void operator= (const ACE_Mutex &) {} + ACE_Mutex (const ACE_Mutex &) {} +}; + +class ACE_Export ACE_Thread_Mutex + // = TITLE + // ACE_Thread_Mutex wrapper (only valid for threads in the same + // process). + // + // = DESCRIPTION + // This implementation is optimized for locking threads that are + // in the same process. It maps to <CRITICAL_SECTION>s on NT + // and <ACE_mutex_t> with <type> set to <USYNC_THREAD> on UNIX. +{ +public: + ACE_Thread_Mutex (LPCTSTR name = 0, void *arg = 0); + + ~ACE_Thread_Mutex (void); + // Implicitly destroy the mutex. + + int remove (void); + // Explicitly destroy the mutex. + + int acquire (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int tryacquire (void); + // Conditionally acquire lock (i.e., don't wait on queue). + + int release (void); + // Release lock and unblock a thread at head of priority queue. + + int acquire_read (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int acquire_write (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int tryacquire_read (void); + // Conditionally acquire a lock (i.e., won't block). + + int tryacquire_write (void); + // Conditionally acquire a lock (i.e., won't block). + + const ACE_thread_mutex_t &lock (void) const; + // Return the underlying mutex. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +//private: + ACE_thread_mutex_t lock_; + // Mutex type that supports single-process locking efficiently. + +private: + // = Prevent assignment and initialization. + void operator= (const ACE_Thread_Mutex &) {} + ACE_Thread_Mutex (const ACE_Thread_Mutex &) {} +}; + +class ACE_Export ACE_Thread_Mutex_Guard + // = TITLE + // This data structure is meant to be used within a method or + // function... It performs automatic aquisition and release of + // an ACE_Mutex. + // + // = DESCRIPTION + // This should be a specialization of ACE_Guard, but compiler + // bugs in older C++ compilers preclude this... +{ +public: + ACE_Thread_Mutex_Guard (ACE_Thread_Mutex &m, int block = 1); + // Implicitly and automatically acquire the lock. + + ~ACE_Thread_Mutex_Guard (void); + // Implicitly release the lock. + + int locked (void); + // 1 if locked, 0 if couldn't acquire the lock (errno will contain + // the reason for this). + + int remove (void); + // Explicitly release the lock. + + int acquire (void); + // Explicitly acquire the lock. + + int tryacquire (void); + // Conditionally acquire the lock (i.e., won't block). + + int release (void); + // Explicitly release the lock. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_Thread_Mutex &lock_; + // Reference to the mutex. + + int owner_; + // Keeps track of whether we acquired the lock or failed. + + // = Prevent assignment and initialization. + void operator= (const ACE_Thread_Mutex_Guard &) {} + ACE_Thread_Mutex_Guard (const ACE_Thread_Mutex_Guard &g): lock_ (g.lock_) {} +}; + +class ACE_Export ACE_Condition_Thread_Mutex + // = TITLE + // ACE_Condition variable wrapper written using ACE_Mutexes This + // allows threads to block until shared data changes state. + // + // = DESCRIPTION + // This should be an instantiation of ACE_Condition but problems + // with compilers precludes this... +{ +public: + ACE_Condition_Thread_Mutex (const ACE_Thread_Mutex &m, + LPCTSTR name = 0, + void *arg = 0); + // Initialize the condition variable. + + ~ACE_Condition_Thread_Mutex (void); + // Implicitly destroy the condition variable. + + int remove (void); + // Explicitly destroy the condition variable. + + int wait (const ACE_Time_Value *abstime); + // Block on condition, or until absolute time-of-day has passed. If + // abstime == 0 use "blocking" <wait> semantics. Else, if <abstime> + // != 0 and the call times out before the condition is signaled + // <wait> returns -1 and sets errno to ETIME. + + int wait (void); + // Block on condition. + + int wait (ACE_Thread_Mutex &mutex, const ACE_Time_Value *abstime = 0); + // Block on condition or until absolute time-of-day has passed. If + // abstime == 0 use "blocking" wait() semantics on the <mutex> + // passed as a parameter (this is useful if you need to store the + // <Condition> in shared memory). Else, if <abstime> != 0 and the + // call times out before the condition is signaled <wait> returns -1 + // and sets errno to ETIME. + + int signal (void); + // Signal one waiting thread. + + int broadcast (void); + // Signal *all* waiting threads. + + ACE_Thread_Mutex &mutex (void); + // Returns a reference to the underlying mutex_; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_cond_t cond_; + // Condition variable. + + ACE_Thread_Mutex &mutex_; + // Reference to mutex lock. + + // = Prevent assignment and initialization. + void operator= (const ACE_Condition_Thread_Mutex &) {} + ACE_Condition_Thread_Mutex (const ACE_Condition_Thread_Mutex &c): mutex_ (c.mutex_) {} +}; + +class ACE_Export ACE_Recursive_Thread_Mutex + // = TITLE + // Implement a C++ wrapper that allows calls to class + // <ACE_Thread_Mutex> to be nested for a nested acquire() that + // occurs in the same thread. + // + // = DESCRIPTION + // This class should be a specialization of the + // ACE_Recursive_Lock template class, but problems with some C++ + // compilers preclude this... +{ + // friend class ACE_Condition<class ACE_COND_MUTEX>; +public: + ACE_Recursive_Thread_Mutex (LPCTSTR name = 0, + void *arg = 0); + // Initialize a recursive mutex. + + ~ACE_Recursive_Thread_Mutex (void); + // Implicitly release a recursive mutex. + + int remove (void); + // Implicitly release a recursive mutex. + + int acquire (void); + // Acquire a recursive mutex (will increment the nesting level and + // not deadmutex if the owner of the mutex calls this method more + // than once). + + int tryacquire (void); + // Conditionally acquire a recursive mutex (i.e., won't block). + + int release (void); + // Releases a recursive mutex (will not release mutex until all the + // nesting level drops to 0, which means the mutex is no longer + // held). + + ACE_thread_t get_thread_id (void); + // Return the id of the thread that currently owns the mutex. + + int get_nesting_level (void); + // Return the nesting level of the recursion. When a thread has + // acquired the mutex for the first time, the nesting level == 1. + // The nesting level is incremented every time the thread acquires + // the mutex recursively. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + // These methods should *not* be public (they hold no locks...) + void set_nesting_level (int d); + void set_thread_id (ACE_thread_t t); + + ACE_Thread_Mutex nesting_mutex_; + // Guards the state of the nesting level and thread id. + + ACE_Condition_Thread_Mutex lock_available_; + // This is the condition variable that actually suspends other + // waiting threads until the mutex is available. + + int nesting_level_; + // Current nesting level of the recursion. + + ACE_thread_t owner_id_; + // Current owner of the lock. + + // = Prevent assignment and initialization. + void operator= (const ACE_Recursive_Thread_Mutex &) {} + ACE_Recursive_Thread_Mutex (const ACE_Recursive_Thread_Mutex &); +}; + +class ACE_Export ACE_RW_Mutex + // = TITLE + // Wrapper for readers/writer locks. + // + // = DESCRIPTION + // These are most useful for applications that have many more + // parallel readers than writers... +{ +public: + ACE_RW_Mutex (int type = USYNC_THREAD, + LPCTSTR name = 0, + void *arg = 0); + // Initialize a readers/writer lock. + + ~ACE_RW_Mutex (void); + // Implicitly destroy a readers/writer lock + + int remove (void); + // Explicitly destroy a readers/writer lock. + + int acquire_read (void); + // Acquire a read lock, but block if a writer hold the lock. + + int acquire_write (void); + // Acquire a write lock, but block if any readers or a + // writer hold the lock. + + int tryacquire_read (void); + // Conditionally acquire a read lock (i.e., won't block). + + int tryacquire_write (void); + // Conditionally acquire a write lock (i.e., won't block). + + int acquire (void); + // Note, for interface uniformity with other synchronization + // wrappers we include the <acquire> method. This is implemented as + // a write-lock to be on the safe-side... + + int tryacquire (void); + // Note, for interface uniformity with other synchronization + // wrappers we include the <tryacquire> method. This is implemented + // as a write-lock to be on the safe-side... + + int release (void); + // Unlock a readers/writer lock. + + const ACE_rwlock_t &lock (void) const; + // Return the underlying lock. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_rwlock_t lock_; + // Readers/writer lock. + + // = Prevent assignment and initialization. + void operator= (const ACE_RW_Mutex &) {} + ACE_RW_Mutex (const ACE_RW_Mutex &) {} +}; + +class ACE_Export ACE_RW_Thread_Mutex : public ACE_RW_Mutex + // = TITLE + // Wrapper for readers/writer locks that exist within a process. +{ +public: + ACE_RW_Thread_Mutex (LPCTSTR name = 0, + void *arg = 0); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Semaphore + // = TITLE + // Wrapper for Dijkstra style general semaphores. +{ +public: + // = Initialization and termination. + ACE_Semaphore (u_int count, + int type = USYNC_THREAD, + LPCTSTR name = 0, + void * = 0, + int max = 0x7fffffff); + // Initialize the semaphore, with default value of "count". + + ~ACE_Semaphore (void); + // Implicitly destroy the semaphore. + + int remove (void); + // Explicitly destroy the semaphore. + + int acquire (void); + // Block the thread until the semaphore count becomes + // greater than 0, then decrement it. + + int tryacquire (void); + // Conditionally decrement the semaphore if count is greater + // than 0 (i.e., won't block). + + int release (void); + // Increment the semaphore, potentially unblocking + // a waiting thread. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + const ACE_sema_t &lock (void) const; + // Return the underlying lock. + +private: + ACE_sema_t semaphore_; + + // = Prevent assignment and initialization. + void operator= (const ACE_Semaphore &) {} + ACE_Semaphore (const ACE_Semaphore &) {} +}; + +class ACE_Export ACE_Thread_Semaphore : public ACE_Semaphore + // = TITLE + // Wrapper for Dijkstra style general semaphores that work + // only within on process. +{ +public: + ACE_Thread_Semaphore (u_int count, LPCTSTR name = 0, + void * = 0, int max = 0x7FFFFFFF); + // Initialize the semaphore, with an initial value of <count> and a + // maximum value of <max>. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Process_Semaphore + // = TITLE + // Wrapper for Dijkstra style general semaphores that work + // across processes. +{ +public: + ACE_Process_Semaphore (u_int count, LPCTSTR name = 0, + void * = 0, int max = 0x7FFFFFFF); + // Initialize the semaphore, with an initial value of <count> and a + // maximum value of <max>. + + ~ACE_Process_Semaphore (void); + // Implicitly destroy the semaphore. + + int remove (void); + // Explicitly destroy the semaphore. + + int acquire (void); + // Block the thread until the semaphore count becomes + // greater than 0, then decrement it. + + int tryacquire (void); + // Conditionally decrement the semaphore if count is greater + // than 0 (i.e., won't block). + + int release (void); + // Increment the semaphore, potentially unblocking + // a waiting thread. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: +#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) + ACE_Semaphore lock_; +#else + ACE_SV_Semaphore_Complex lock_; + // We need this to get the right semantics... +#endif /* ACE_WIN32 */ +}; + +struct ACE_Export ACE_Sub_Barrier +{ + // = Initialization. + ACE_Sub_Barrier (u_int count, + ACE_Thread_Mutex &lock, + LPCTSTR name = 0, + void *arg = 0); + + ACE_Condition_Thread_Mutex barrier_finished_; + // True if this generation of the barrier is done. + + int running_threads_; + // Number of threads that are still running. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Barrier + // = TITLE + // Implements "barrier synchronization". + // + // = DESCRIPTION + // This class allows <count> number of threads to synchronize + // their completion (so-called "barrier synchronization"). The + // implementation uses a "sub-barrier generation numbering" + // scheme to avoid overhead and to ensure that all threads exit + // the barrier correct. This code is based on an article from + // SunOpsis Vol. 4, No. 1 by Richard Marejka + // (Richard.Marejka@canada.sun.com). +{ +public: + ACE_Barrier (u_int count, + LPCTSTR name = 0, + void *arg = 0); + // Initialize the barrier to synchronize <count> threads. + + int wait (void); + // Block the caller until all <count> threads have called <wait> and + // then allow all the caller threads to continue in parallel. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Thread_Mutex lock_; + // Serialize access to the barrier state. + + int current_generation_; + // Either 0 or 1, depending on whether we are the first generation + // of waiters or the next generation of waiters. + + int count_; + // Total number of threads that can be waiting at any one time. + + ACE_Sub_Barrier sub_barrier_1_; + ACE_Sub_Barrier sub_barrier_2_; + ACE_Sub_Barrier *sub_barrier_[2]; + // We keep two <sub_barriers>, one for the first "generation" of + // waiters, and one for the next "generation" of waiters. This + // efficiently solves the problem of what to do if all the first + // generation waiters don't leave the barrier before one of the + // threads calls wait() again (i.e., starts up the next generation + // barrier). + + // = Prevent assignment and initialization. + void operator= (const ACE_Barrier &) {} + ACE_Barrier (const ACE_Barrier &): sub_barrier_1_ (0, lock_), sub_barrier_2_ (0, lock_) {} +}; + +#if 0 +class ACE_Export ACE_Process_Barrier : public ACE_Barrier + // = TITLE + // Implements "barrier synchronization" using ACE_Process_Mutexes! + // + // = DESCRIPTION + // This class is just a simple wrapper for ACE_Barrier that + // selects the USYNC_PROCESS variant for the locks. +{ +public: + ACE_Process_Barrier (u_int count, LPCTSTR name = 0); + // Create a Process_Barrier, passing in the optional <name>. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; +#endif /* 0 */ + +class ACE_Export ACE_Thread_Barrier : public ACE_Barrier + // = TITLE + // Implements "barrier synchronization" using ACE_Thread_Mutexes! + // + // = DESCRIPTION + // This class is just a simple wrapper for ACE_Barrier that + // selects the USYNC_THREAD variant for the locks. +{ +public: + ACE_Thread_Barrier (u_int count, LPCTSTR name = 0); + // Create a Process_Barrier, passing in the optional <name>. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#endif /* ACE_HAS_THREADS */ + +class ACE_Export ACE_Process_Mutex + // = TITLE + // ACE_Mutex wrapper (valid in same process, as well as across + // processes). +{ +public: + ACE_Process_Mutex (LPCTSTR name = ACE_DEFAULT_MUTEX, void *arg = 0); + // Create a Process_Mutex, passing in the optional <name>. + + ~ACE_Process_Mutex (void); + + int remove (void); + // Explicitly destroy the mutex. + + int acquire (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int tryacquire (void); + // Conditionally acquire lock (i.e., don't wait on queue). + + int release (void); + // Release lock and unblock a thread at head of priority queue. + + int acquire_read (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int acquire_write (void); + // Acquire lock ownership (wait on priority queue if necessary). + + int tryacquire_read (void); + // Conditionally acquire a lock (i.e., won't block). + + int tryacquire_write (void); + // Conditionally acquire a lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +#if defined (ACE_WIN32) || defined (ACE_HAS_POSIX_SEM) + ACE_Mutex lock_; +#else + ACE_SV_Semaphore_Complex lock_; + // We need this to get the right semantics... +#endif /* ACE_WIN32 */ +}; + +class ACE_Export ACE_RW_Process_Mutex : public ACE_Process_Mutex + // = TITLE + // Wrapper for readers/writer locks that exist across processes. +{ +public: + ACE_RW_Process_Mutex (LPCTSTR name = ACE_DEFAULT_MUTEX, + void *arg = 0); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Null_Barrier + // = TITLE + // Implements "NULL barrier synchronization". +{ +public: + ACE_Null_Barrier (u_int, + const char * = 0, + void * = 0) {} + // Initialize the barrier to synchronize <count> threads. + + int wait (void) { return 0; } + // Block the caller until all <count> threads have called <wait> and + // then allow all the caller threads to continue in parallel. + + void dump (void) const {} + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + + // = Prevent assignment and initialization. + void operator= (const ACE_Null_Barrier &) {} + ACE_Null_Barrier (const ACE_Null_Barrier &) {} +}; + +class ACE_Export ACE_Null_Mutex + // = TITLE + // Implement a do nothing <ACE_Mutex>, i.e., all the methods are + // no ops. +{ +public: + ACE_Null_Mutex (LPCTSTR = 0) {} + ~ACE_Null_Mutex (void) {} + int remove (void) { return 0; } + + int acquire (void) { return 0; } + int tryacquire (void) { return 0; } + int release (void) { return 0; } + int acquire_write (void) { return 0; } + int tryacquire_write (void) { return 0; } + int acquire_read (void) { return 0; } + int tryacquire_read (void) { return 0; } + + void dump (void) const { } + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +class ACE_Export ACE_Null_Condition_Mutex + // = TITLE + // Implement a do nothing <ACE_Condition> variable wrapper, i.e., + // all methods are no ops. This class is necessary since some + // C++ compilers are *very* lame... +{ +public: + ACE_Null_Condition_Mutex (ACE_Null_Mutex &m, int = 0, + LPCTSTR = 0, void * = 0): mutex_ (m) {} + ~ACE_Null_Condition_Mutex (void) {} + int remove (void) { return 0; } + int wait (ACE_Time_Value * = 0) { return 0; } + int signal (void) { return 0; } + int broadcast (void) { return 0; } + ACE_Null_Mutex &mutex (void) { return this->mutex_; } + + void dump (void) const {} + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Null_Mutex &mutex_; // Reference to mutex lock. + + // = Prevent assignment and initialization. + void operator= (const ACE_Null_Condition_Mutex &) {} + ACE_Null_Condition_Mutex (const ACE_Null_Condition_Mutex &c): mutex_ (c.mutex_) {} +}; + +class ACE_Export ACE_Null_Mutex_Guard + // = TITLE + // This data structure is meant to be used within a method or + // function... It performs automatic aquisition and release of + // an ACE_Null_Mutex. + // + // = DESCRIPTION + // This should be a specialization of ACE_Guard, but compiler + // bugs preclude this... +{ +public: + ACE_Null_Mutex_Guard (ACE_Null_Mutex &) {} + ~ACE_Null_Mutex_Guard (void) {} + int remove (void) { return 0; } + int locked (void) { return 1; } + int acquire (void) { return 0; } + int tryacquire (void) { return 0; } + int release (void) { return 0; } + void dump (void) const { } + +protected: + // = Prevent assignment and initialization. + void operator= (const ACE_Null_Mutex_Guard &) {} + ACE_Null_Mutex_Guard (const ACE_Null_Mutex_Guard &) {} +}; + +#if defined (__ACE_INLINE__) +#include "ace/Synch.i" +#endif /* __ACE_INLINE__ */ + +// Include the templates here. +#include "ace/Synch_T.h" + +#endif /* ACE_SYNCH_H */ diff --git a/ace/Synch.i b/ace/Synch.i new file mode 100644 index 00000000000..02544228354 --- /dev/null +++ b/ace/Synch.i @@ -0,0 +1,421 @@ +/* -*- C++ -*- */ +// $Id$ + +// Synch.i + +ACE_INLINE int +ACE_File_Lock::acquire_read (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::acquire_read"); + return ACE_OS::flock_rdlock (&this->lock_, whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::tryacquire_read (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::tryacquire_read"); + return ACE_OS::flock_tryrdlock (&this->lock_, whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::tryacquire_write (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::tryacquire_write"); + return ACE_OS::flock_trywrlock (&this->lock_, whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::tryacquire (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::tryacquire"); + return this->tryacquire_write (whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::acquire_write (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::acquire_write"); + return ACE_OS::flock_wrlock (&this->lock_, whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::acquire (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::acquire"); + return this->acquire_write (whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::release (short whence, off_t start, off_t len) +{ +// ACE_TRACE ("ACE_File_Lock::release"); + return ACE_OS::flock_unlock (&this->lock_, whence, start, len); +} + +ACE_INLINE int +ACE_File_Lock::remove (void) +{ +// ACE_TRACE ("ACE_File_Lock::remove"); + + return ACE_OS::flock_destroy (&this->lock_); +} + +ACE_INLINE ACE_HANDLE +ACE_File_Lock::get_handle (void) +{ +// ACE_TRACE ("ACE_File_Lock::get_handle"); + return this->lock_.handle_; +} + +ACE_INLINE void +ACE_File_Lock::set_handle (ACE_HANDLE h) +{ +// ACE_TRACE ("ACE_File_Lock::set_handle"); + this->lock_.handle_ = h; +} + +#if defined (ACE_HAS_THREADS) + +ACE_INLINE const ACE_sema_t & +ACE_Semaphore::lock (void) const +{ +// ACE_TRACE ("ACE_Semaphore::lock"); + return this->semaphore_; +} + +ACE_INLINE int +ACE_Semaphore::remove (void) +{ +// ACE_TRACE ("ACE_Semaphore::remove"); + return ACE_OS::sema_destroy (&this->semaphore_); +} + +ACE_INLINE int +ACE_Semaphore::acquire (void) +{ +// ACE_TRACE ("ACE_Semaphore::acquire"); + return ACE_OS::sema_wait (&this->semaphore_); +} + +ACE_INLINE int +ACE_Semaphore::tryacquire (void) +{ +// ACE_TRACE ("ACE_Semaphore::tryacquire"); + return ACE_OS::sema_trywait (&this->semaphore_); +} + +ACE_INLINE int +ACE_Semaphore::release (void) +{ +// ACE_TRACE ("ACE_Semaphore::release"); + return ACE_OS::sema_post (&this->semaphore_); +} + +ACE_INLINE int +ACE_Mutex::acquire_read (void) +{ +// ACE_TRACE ("ACE_Mutex::acquire_read"); + return ACE_OS::mutex_lock (&this->lock_); +} + +ACE_INLINE int +ACE_Mutex::acquire_write (void) +{ +// ACE_TRACE ("ACE_Mutex::acquire_write"); + return ACE_OS::mutex_lock (&this->lock_); +} + +ACE_INLINE int +ACE_Mutex::tryacquire_read (void) +{ +// ACE_TRACE ("ACE_Mutex::tryacquire_read"); + return ACE_OS::mutex_trylock (&this->lock_); +} + +ACE_INLINE const ACE_mutex_t & +ACE_Mutex::lock (void) const +{ +// ACE_TRACE ("ACE_Mutex::lock"); + return this->lock_; +} + +ACE_INLINE int +ACE_Mutex::tryacquire_write (void) +{ +// ACE_TRACE ("ACE_Mutex::tryacquire_write"); + return ACE_OS::mutex_trylock (&this->lock_); +} + +ACE_INLINE int +ACE_Mutex::acquire (void) +{ +// ACE_TRACE ("ACE_Mutex::acquire"); + return ACE_OS::mutex_lock (&this->lock_); +} + +ACE_INLINE int +ACE_Mutex::tryacquire (void) +{ +// ACE_TRACE ("ACE_Mutex::tryacquire"); + return ACE_OS::mutex_trylock (&this->lock_); +} + +ACE_INLINE int +ACE_Mutex::release (void) +{ +// ACE_TRACE ("ACE_Mutex::release"); + return ACE_OS::mutex_unlock (&this->lock_); +} + +ACE_INLINE int +ACE_Mutex::remove (void) +{ +// ACE_TRACE ("ACE_Mutex::remove"); + return ACE_OS::mutex_destroy (&this->lock_); +} + +ACE_INLINE const ACE_thread_mutex_t & +ACE_Thread_Mutex::lock (void) const +{ +// ACE_TRACE ("ACE_Thread_Mutex::lock"); + return this->lock_; +} + +ACE_INLINE int +ACE_Thread_Mutex::acquire_read (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::acquire_read"); + return ACE_OS::thread_mutex_lock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::acquire_write (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::acquire_write"); + return ACE_OS::thread_mutex_lock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::tryacquire_read (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::tryacquire_read"); + return ACE_OS::thread_mutex_trylock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::tryacquire_write (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::tryacquire_write"); + return ACE_OS::thread_mutex_trylock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::acquire (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::acquire"); + return ACE_OS::thread_mutex_lock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::tryacquire (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::tryacquire"); + return ACE_OS::thread_mutex_trylock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::release (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::release"); + return ACE_OS::thread_mutex_unlock (&this->lock_); +} + +ACE_INLINE int +ACE_Thread_Mutex::remove (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex::remove"); + return ACE_OS::thread_mutex_destroy (&this->lock_); +} + +// Implicitly and automatically acquire the lock. + +ACE_INLINE +ACE_Thread_Mutex_Guard::ACE_Thread_Mutex_Guard (ACE_Thread_Mutex &m, + int block) + : lock_ (m) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::ACE_Thread_Mutex_Guard"); + this->owner_ == block ? this->lock_.acquire () : this->lock_.tryacquire (); +} + +// Implicitly release the lock. + +ACE_INLINE +ACE_Thread_Mutex_Guard::~ACE_Thread_Mutex_Guard (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::~ACE_Thread_Mutex_Guard"); + if (this->owner_ != -1) + this->lock_.release (); +} + +ACE_INLINE int +ACE_Thread_Mutex_Guard::locked (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::locked"); + return this->owner_ != -1; +} + +// Explicitly acquire the lock. + +ACE_INLINE int +ACE_Thread_Mutex_Guard::acquire (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::acquire"); + return this->owner_ = this->lock_.acquire (); +} + +// Conditionally acquire the lock (i.e., won't block). + +ACE_INLINE int +ACE_Thread_Mutex_Guard::tryacquire (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::tryacquire"); + return this->owner_ = this->lock_.tryacquire (); +} + +// Explicitly release the lock. + +ACE_INLINE int +ACE_Thread_Mutex_Guard::release (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::release"); + this->owner_ = -1; + return this->lock_.release (); +} + +// Explicitly release the lock. + +ACE_INLINE int +ACE_Thread_Mutex_Guard::remove (void) +{ +// ACE_TRACE ("ACE_Thread_Mutex_Guard::remove"); + return this->release (); +} + +ACE_INLINE int +ACE_Condition_Thread_Mutex::remove (void) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::remove"); + + // cond_destroy() is called in a loop if the condition variable is + // BUSY. This avoids a condition where a condition is signaled and + // because of some timing problem, the thread that is to be signaled + // has called the cond_wait routine after the signal call. Since + // the condition signal is not queued in any way, deadlock occurs. + + int result = 0; + + while ((result = ACE_OS::cond_destroy (&this->cond_)) == -1 + && errno == EBUSY) + { + ACE_OS::cond_broadcast (&this->cond_); + ACE_OS::thr_yield (); + } + + return result; +} + +ACE_INLINE ACE_Thread_Mutex & +ACE_Condition_Thread_Mutex::mutex (void) +{ +// ACE_TRACE ("ACE_Condition_Thread_Mutex::mutex"); + return this->mutex_; +} + +ACE_INLINE int +ACE_Recursive_Thread_Mutex::remove (void) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::remove"); + this->nesting_mutex_.remove (); + return this->lock_available_.remove (); +} + +ACE_INLINE void +ACE_Recursive_Thread_Mutex::set_thread_id (ACE_thread_t t) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::set_thread_id"); + this->owner_id_ = t; +} + +ACE_INLINE void +ACE_Recursive_Thread_Mutex::set_nesting_level (int d) +{ +// ACE_TRACE ("ACE_Recursive_Thread_Mutex::set_nesting_level"); + this->nesting_level_ = d; +} + +ACE_INLINE const ACE_rwlock_t & +ACE_RW_Mutex::lock (void) const +{ +// ACE_TRACE ("ACE_RW_Mutex::lock"); + return this->lock_; +} + +ACE_INLINE int +ACE_RW_Mutex::remove (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::remove"); + return ACE_OS::rwlock_destroy (&this->lock_); +} + +ACE_INLINE int +ACE_RW_Mutex::acquire_read (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::acquire_read"); + return ACE_OS::rw_rdlock (&this->lock_); +} + +ACE_INLINE int +ACE_RW_Mutex::acquire_write (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::acquire_write"); + return ACE_OS::rw_wrlock (&this->lock_); +} + +ACE_INLINE int +ACE_RW_Mutex::acquire (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::acquire"); + return ACE_OS::rw_wrlock (&this->lock_); +} + +ACE_INLINE int +ACE_RW_Mutex::tryacquire_read (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::tryacquire_read"); + return ACE_OS::rw_tryrdlock (&this->lock_); +} + +ACE_INLINE int +ACE_RW_Mutex::tryacquire_write (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::tryacquire_write"); + return ACE_OS::rw_trywrlock (&this->lock_); +} + +ACE_INLINE int +ACE_RW_Mutex::tryacquire (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::tryacquire"); + return this->tryacquire_write (); +} + +ACE_INLINE int +ACE_RW_Mutex::release (void) +{ +// ACE_TRACE ("ACE_RW_Mutex::release"); + return ACE_OS::rw_unlock (&this->lock_); +} + +#endif /* ACE_HAS_THREADS */ + diff --git a/ace/Synch_Options.cpp b/ace/Synch_Options.cpp new file mode 100644 index 00000000000..738d02493b1 --- /dev/null +++ b/ace/Synch_Options.cpp @@ -0,0 +1,93 @@ +// Synch_Options.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Synch_Options.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_Synch_Options) + +void +ACE_Synch_Options::dump (void) const +{ + ACE_TRACE ("ACE_Synch_Options::dump"); +} + +// Static initialization. + +/* static */ +ACE_Synch_Options ACE_Synch_Options::defaults; + +/* static */ +ACE_Synch_Options ACE_Synch_Options::synch; + +/* static */ +ACE_Synch_Options ACE_Synch_Options::asynch (ACE_Synch_Options::USE_REACTOR); + +ACE_Synch_Options::ACE_Synch_Options (u_long options, + const ACE_Time_Value &timeout, + const void *arg) +{ + ACE_TRACE ("ACE_Synch_Options::ACE_Synch_Options"); + this->set (options, timeout, arg); +} + +void +ACE_Synch_Options::set (u_long options, + const ACE_Time_Value &timeout, + const void *arg) +{ + ACE_TRACE ("ACE_Synch_Options::set"); + this->options_ = options; + this->timeout_ = (ACE_Time_Value &) timeout; + this->arg_ = arg; +} + +int +ACE_Synch_Options::operator[] (u_long option) const +{ + ACE_TRACE ("ACE_Synch_Options::operator[]"); + return (this->options_ & option) != 0; +} + +void +ACE_Synch_Options::operator= (u_long option) +{ + ACE_TRACE ("ACE_Synch_Options::operator="); + this->options_ |= option; +} + +const ACE_Time_Value & +ACE_Synch_Options::timeout (void) const +{ + ACE_TRACE ("ACE_Synch_Options::timeout"); + return this->timeout_; +} + +void +ACE_Synch_Options::timeout (ACE_Time_Value &tv) +{ + ACE_TRACE ("ACE_Synch_Options::timeout"); + this->timeout_ = tv; +} + +const ACE_Time_Value * +ACE_Synch_Options::time_value (void) const +{ + ACE_TRACE ("ACE_Synch_Options::time_value"); + return (*this)[USE_TIMEOUT] ? &this->timeout_ : 0; +} + +const void * +ACE_Synch_Options::arg (void) const +{ + ACE_TRACE ("ACE_Synch_Options::arg"); + return this->arg_; +} + +void +ACE_Synch_Options::arg (const void *a) +{ + ACE_TRACE ("ACE_Synch_Options::arg"); + this->arg_ = a; +} + diff --git a/ace/Synch_Options.h b/ace/Synch_Options.h new file mode 100644 index 00000000000..28e3300013c --- /dev/null +++ b/ace/Synch_Options.h @@ -0,0 +1,135 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// ACE_Synch_Options.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SYNCH_OPTIONS_H) +#define ACE_SYNCH_OPTIONS_H + +#include "ace/ACE.h" + +class ACE_Export ACE_Synch_Options + // = TITLE + // Contains the values of options used to determine the + // synchronous and asynchronous behavior. + // + // DESCRIPTION = + // Values support the following behavior (TV == "timeout" + // and UR == "use ACE_Reactor"): + // + // Parameters | Description + // | + // TV | UR | + // -----|----------|------------------------------- + // | | + // NULL | yes | infinite timeout (using ACE_Reactor) + // | | + // time | yes | try asynch transaction for + // | | the specified time (using ACE_Reactor) + // | | + // 0,0 | yes | poll; try, if EWOULDBLOCK, + // | | then return immediately + // | | (using ACE_Reactor) + // | | + // NULL | no | block forever (don't use ACE_Reactor) + // | | + // time | no | do a blocking transaction + // | | for the specified time + // | | (don't use ACE_Reactor) + // | | + // 0,0 | no | poll; but do not initiate a + // | | nonblocking transaction + // | | (don't use ACE_Reactor) +{ +public: + // = Options flags for controlling synchronization. Note that these + // flags can be bit-wise "or'd" together if both options are + // desired. + enum + { + USE_REACTOR = 01, + // Use the Reactor. + USE_TIMEOUT = 02 + // Interprete the Time_Value. + }; + + // = Initialization methods. + ACE_Synch_Options (u_long options = 0, + const ACE_Time_Value &timeout = ACE_Time_Value::zero, + const void *arg = 0); + // Initialize the Synch_Options based on parameters. + + void set (u_long options = 0, + const ACE_Time_Value &timeout = ACE_Time_Value::zero, + const void *arg = 0); + // Initialize the Synch_Options based on parameters. + + int operator[] (u_long option) const; + // Get method for determining which options are enabled. + + void operator= (u_long option); + // Set method for enabling certain options. + + const void *arg (void) const; + // Returns the "magic cookie" argument. + + void arg (const void *); + // Set the "magic cookie" argument. + + const ACE_Time_Value &timeout (void) const; + // Returns a reference to the <Time_Value>. This value only makes + // sense if (*this)[USE_TIMEOUT] is true. + + void timeout (ACE_Time_Value &tv); + // Set the <Time_Value>. + + const ACE_Time_Value *time_value (void) const; + // Returns the address of the timeout <Time_Value> if + // (*this)[USE_TIMEOUT] is true, else 0. This should be used with + // care, e.g., the timeout pointer should not be stored in a manner + // that will lead to dangling pointers... + + // = Static data members (singletons) + + static ACE_Synch_Options defaults; + // This is the default setting for options, which will block + // synchronously. + + static ACE_Synch_Options synch; + // This is the default synchronous setting. + + static ACE_Synch_Options asynch; + // This is the default asynchronous setting. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + u_long options_; + // Keeps track of the enabled options. + + ACE_Time_Value timeout_; + // Amount of time to wait for timeouts. + + const void *arg_; + // "Magic cookie" always passed in as an argument to the ACE_Reactor's + // <schedule_timer> method. Used to communicate values for + // asynchronous programming. +}; + +#endif /* ACE_SYNCH_OPTIONS_H */ diff --git a/ace/Synch_Options.i b/ace/Synch_Options.i new file mode 100644 index 00000000000..0a31ce8c554 --- /dev/null +++ b/ace/Synch_Options.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Synch_Options.i diff --git a/ace/Synch_T.cpp b/ace/Synch_T.cpp new file mode 100644 index 00000000000..d9389f139a2 --- /dev/null +++ b/ace/Synch_T.cpp @@ -0,0 +1,626 @@ +// Synch_T.cpp +// $Id$ + +#if !defined (ACE_SYNCH_T_C) +#define ACE_SYNCH_T_C + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Thread.h" +#include "ace/Time_Value.h" +#include "ace/Synch_T.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Synch_T.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Atomic_Op) + +template <class LOCK, class TYPE> +ACE_Test_and_Set<LOCK, TYPE>::ACE_Test_and_Set (TYPE initial_value) + : is_set_ (initial_value) +{ +} + +// Returns true if we are done, else false. +template <class LOCK, class TYPE> TYPE +ACE_Test_and_Set<LOCK, TYPE>::is_set (void) const +{ + ACE_GUARD_RETURN (LOCK, ace_mon, (LOCK &) this->lock_, this->is_set_); + return this->is_set_; +} + +// Sets the <is_set_> status. +template <class LOCK, class TYPE> TYPE +ACE_Test_and_Set<LOCK, TYPE>::set (TYPE status) +{ + ACE_GUARD_RETURN (LOCK, ace_mon, this->lock_, this->is_set_); + TYPE o_status = this->is_set_; + this->is_set_ = status; + return o_status; +} + +template <class LOCK, class TYPE> int +ACE_Test_and_Set<LOCK, TYPE>::handle_signal (int signum, siginfo_t *, ucontext_t *) +{ + this->set (1); + return 0; +} + +template <class LOCK, class TYPE> void +ACE_Atomic_Op<LOCK, TYPE>::dump (void) const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->lock_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class LOCK, class TYPE> +ACE_Atomic_Op<LOCK, TYPE>::ACE_Atomic_Op (void) + : value_ (0) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::ACE_Atomic_Op"); +} + +template <class LOCK, class TYPE> +ACE_Atomic_Op<LOCK, TYPE>::ACE_Atomic_Op (TYPE c) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::ACE_Atomic_Op"); + this->value_ = c; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Guard) + +template <class LOCK> void +ACE_Guard<LOCK>::dump (void) const +{ +// ACE_TRACE ("ACE_Guard<LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "lock_ = %x\n", this->lock_)); + ACE_DEBUG ((LM_DEBUG, "owner_ = %d\n", this->owner_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Write_Guard) + +template <class LOCK> void +ACE_Write_Guard<LOCK>::dump (void) const +{ +// ACE_TRACE ("ACE_Write_Guard<LOCK>::dump"); + ACE_Guard<LOCK>::dump (); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Read_Guard) + +template <class LOCK> void +ACE_Read_Guard<LOCK>::dump (void) const +{ +// ACE_TRACE ("ACE_Read_Guard<LOCK>::dump"); + ACE_Guard<LOCK>::dump (); +} + +#if defined (ACE_HAS_THREADS) + +#if defined (__osf__) && ! defined (__GNUG__) +#pragma define_template ACE_Condition<ACE_Mutex> +#endif + +ACE_ALLOC_HOOK_DEFINE(ACE_Condition) + +template <class MUTEX> void +ACE_Condition<MUTEX>::dump (void) const +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class MUTEX> +ACE_Thread_Condition<MUTEX>::ACE_Thread_Condition (MUTEX &m, + LPCTSTR name, + void *arg) + : ACE_Condition<MUTEX> (m, USYNC_THREAD, name, arg) +{ +// ACE_TRACE ("ACE_Thread_Condition<MUTEX>::ACE_Thread_Condition"); +} + +template <class MUTEX> void +ACE_Thread_Condition<MUTEX>::dump (void) const +{ +// ACE_TRACE ("ACE_Thread_Condition<MUTEX>::dump"); + + ACE_Condition<MUTEX>::dump (); +} + +template <class MUTEX> void +ACE_Process_Condition<MUTEX>::dump (void) const +{ +// ACE_TRACE ("ACE_Process_Condition<MUTEX>::dump"); + + ACE_Condition<MUTEX>::dump (); +} + +template <class MUTEX> +ACE_Process_Condition<MUTEX>::ACE_Process_Condition (MUTEX &m, + LPCTSTR name, + void *arg) + : ACE_Condition<MUTEX> (m, USYNC_PROCESS, name, arg) +{ +// ACE_TRACE ("ACE_Process_Condition<MUTEX>::ACE_Process_Condition"); +} + +template <class MUTEX> +ACE_Condition<MUTEX>::ACE_Condition (MUTEX &m, + int type, + LPCTSTR name, + void *arg) + : mutex_ (m) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::ACE_Condition"); + if (ACE_OS::cond_init (&this->cond_, type, name, arg) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Condition::ACE_Condition")); +} + +template <class MUTEX> +ACE_Condition<MUTEX>::~ACE_Condition (void) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::~ACE_Condition"); + if (this->remove () == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Condition::~ACE_Condition")); +} + +template <class MUTEX> int +ACE_Condition<MUTEX>::wait (void) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::wait"); + return ACE_OS::cond_wait (&this->cond_, this->mutex_.lock_); +} + +template <class MUTEX> int +ACE_Condition<MUTEX>::wait (MUTEX &mutex, + const ACE_Time_Value *abstime) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::wait"); + if (abstime == 0) + return this->wait (); + else + return ACE_OS::cond_timedwait (&this->cond_, + &mutex.lock_, + (ACE_Time_Value *) abstime); +} + +// Peform an "alertable" timed wait. If the argument ABSTIME == 0 +// then we do a regular cond_wait(), else we do a timed wait for up to +// ABSTIME using the Solaris cond_timedwait() function. + +template <class MUTEX> int +ACE_Condition<MUTEX>::wait (const ACE_Time_Value *abstime) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::wait"); + return this->wait (this->mutex_, abstime); +} +#endif /* ACE_HAS_THREADS */ + +ACE_ALLOC_HOOK_DEFINE(ACE_TSS) + +template <class TYPE> +ACE_TSS<TYPE>::~ACE_TSS (void) +{ + ACE_OS::thr_key_detach (this); +} + +template <class TYPE> TYPE * +ACE_TSS<TYPE>::operator-> () const +{ + return this->ts_get (); +} + +template <class TYPE> +ACE_TSS<TYPE>::operator TYPE *(void) const +{ + return this->ts_get (); +} + +template <class TYPE> TYPE * +ACE_TSS<TYPE>::make_TSS_TYPE (void) const +{ + return new TYPE; +} + +template <class TYPE> void +ACE_TSS<TYPE>::dump (void) const +{ +// ACE_TRACE ("ACE_TSS<TYPE>::dump"); +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->keylock_.dump (); + ACE_DEBUG ((LM_DEBUG, "key_ = %d\n", this->key_)); + ACE_DEBUG ((LM_DEBUG, "\nonce_ = %d", this->once_)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) */ +} + +#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) +template <class TYPE> ACE_INLINE +ACE_TSS<TYPE>::ACE_TSS (TYPE *) +{ +} + +template <class TYPE> ACE_INLINE TYPE * +ACE_TSS<TYPE>::ts_object (void) const +{ + return (TYPE *) &this->type_; +} + +template <class TYPE> ACE_INLINE TYPE * +ACE_TSS<TYPE>::ts_object (TYPE *) +{ + return &this->type_; +} + +template <class TYPE> ACE_INLINE TYPE * +ACE_TSS<TYPE>::ts_get (void) const +{ + return (TYPE *) &this->type_; +} +#else +template <class TYPE> +ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj) + : once_ (0), + key_ (0) +{ + // If caller has passed us a non-NULL TYPE *, then we'll just use + // this to initialize the thread-specific value. Thus, subsequent + // calls to operator->() will return this value. This is useful + // since it enables us to assign objects to thread-specific data + // that have arbitrarily complex constructors! + + if (ts_obj != 0) + { + ACE_ASSERT (this->once_ == 0); + + if (ACE_Thread::keycreate (&this->key_, + &ACE_TSS<TYPE>::cleanup, + (void *) this) != 0) + { + int errnum = errno; + // What should we do if this call fails?! + ACE_OS::fprintf (stderr, "ACE_Thread::keycreate() failed!"); + errno = errnum; + return; + } + + this->once_ = 1; + + if (ACE_Thread::setspecific (this->key_, (void *) ts_obj) != 0) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Thread::setspecific() failed!")); + } +} + +template <class TYPE> TYPE * +ACE_TSS<TYPE>::ts_get (void) const +{ + // Create and initialize thread-specific ts_obj. + if (this->once_ == 0) + { + // Insure that we are serialized! + ACE_GUARD_RETURN (ACE_Mutex, ace_mon, (ACE_Mutex &) this->keylock_, 0); + + // 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; + } + } + + TYPE *ts_obj = 0; + + // Get the ts_obj from thread-specific storage. Note that no locks + // are required here... + if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) + return 0; // This should not happen! + + // Check to see if this is the first time in for this thread. + if (ts_obj == 0) + { + // Allocate memory off the heap and store it in a pointer in + // thread-specific storage (on the stack...). + + ts_obj = this->make_TSS_TYPE (); + + if (ts_obj == 0) + return 0; + + // Store the dynamically allocated pointer in thread-specific + // storage. + if (ACE_Thread::setspecific (this->key_, (void *) ts_obj) != 0) + { + delete ts_obj; + return 0; // Major problems, this should *never* happen! + } + } + + return ts_obj; +} + +// Get the thread-specific object for the key associated with this +// object. Returns 0 if the ts_obj has never been initialized, +// otherwise returns a pointer to the ts_obj. + +template <class TYPE> TYPE * +ACE_TSS<TYPE>::ts_object (void) const +{ + // Ensure that we are serialized! + ACE_GUARD_RETURN (ACE_Mutex, ace_mon, (ACE_Mutex &) this->keylock_, 0); + + if (this->once_ == 0) // Return 0 if we've never been initialized. + return 0; + else + { + TYPE *ts_obj = 0; + + if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) + return 0; // This should not happen! + else + return ts_obj; + } +} + +template <class TYPE> TYPE * +ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj) +{ + // Ensure that we are serialized! + ACE_GUARD_RETURN (ACE_Mutex, ace_mon, this->keylock_, 0); + + if (this->once_ == 0) // Return 0 if we've never been initialized. + return 0; + else + { + TYPE *ts_obj = 0; + + if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) + return 0; // This should not happen! + if (ACE_Thread::setspecific (this->key_, (void *) new_ts_obj) == -1) + return ts_obj; // This should not happen! + else + return ts_obj; + } +} + +/* static */ +template <class TYPE> void +ACE_TSS<TYPE>::cleanup (void *ptr) +{ + // This cast is necessary to invoke the destructor (if necessary). + delete (TYPE *) ptr; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_TSS_Guard) + +template <class LOCK> void +ACE_TSS_Guard<LOCK>::dump (void) const +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "key_ = %d", this->key_)); + ACE_DEBUG ((LM_DEBUG, "\n")); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class LOCK> void +ACE_TSS_Guard<LOCK>::init_key (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::init_key"); + + this->key_ = 0; + ACE_Thread::keycreate (&this->key_, + &ACE_TSS_Guard<LOCK>::cleanup, + (void *) this); +} + +template <class LOCK> +ACE_TSS_Guard<LOCK>::ACE_TSS_Guard (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::ACE_TSS_Guard"); + this->init_key (); +} + +template <class LOCK> int +ACE_TSS_Guard<LOCK>::release (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::release"); + + ACE_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->release (); +} + +template <class LOCK> int +ACE_TSS_Guard<LOCK>::remove (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::remove"); + + ACE_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->remove (); +} + +template <class LOCK> +ACE_TSS_Guard<LOCK>::~ACE_TSS_Guard (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::~ACE_TSS_Guard"); + + ACE_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + // Make sure that this pointer is NULL when we shut down... + ACE_Thread::setspecific (this->key_, 0); + ACE_Thread::keyfree (this->key_); + // Destructor releases lock. + delete guard; +} + +template <class LOCK> void +ACE_TSS_Guard<LOCK>::cleanup (void *ptr) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::dump"); + + // Destructor releases lock. + delete (ACE_Guard<LOCK> *) ptr; +} + +template <class LOCK> +ACE_TSS_Guard<LOCK>::ACE_TSS_Guard (LOCK &lock, int block) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::ACE_TSS_Guard"); + + this->init_key (); + ACE_Guard<LOCK> *guard; + ACE_NEW (guard, ACE_Guard<LOCK> (lock, block)); + ACE_Thread::setspecific (this->key_, (void *) guard); +} + +template <class LOCK> int +ACE_TSS_Guard<LOCK>::acquire (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::acquire"); + + ACE_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->acquire (); +} + +template <class LOCK> int +ACE_TSS_Guard<LOCK>::tryacquire (void) +{ +// ACE_TRACE ("ACE_TSS_Guard<LOCK>::tryacquire"); + + ACE_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->tryacquire (); +} + +template <class LOCK> +ACE_TSS_Write_Guard<LOCK>::ACE_TSS_Write_Guard (LOCK &lock, int block) +{ +// ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::ACE_TSS_Write_Guard"); + + this->init_key (); + ACE_Guard<LOCK> *guard; + ACE_NEW (guard, ACE_Write_Guard<LOCK> (lock, block)); + ACE_Thread::setspecific (this->key_, (void *) guard); +} + +template <class LOCK> int +ACE_TSS_Write_Guard<LOCK>::acquire (void) +{ +// ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::acquire"); + + ACE_Write_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->acquire_write (); +} + +template <class LOCK> int +ACE_TSS_Write_Guard<LOCK>::tryacquire (void) +{ +// ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::tryacquire"); + + ACE_Write_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->tryacquire_write (); +} + +template <class LOCK> int +ACE_TSS_Write_Guard<LOCK>::acquire_write (void) +{ +// ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::acquire_write"); + + return this->acquire (); +} + +template <class LOCK> int +ACE_TSS_Write_Guard<LOCK>::tryacquire_write (void) +{ +// ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::tryacquire_write"); + + return this->tryacquire (); +} + +template <class LOCK> void +ACE_TSS_Write_Guard<LOCK>::dump (void) const +{ +// ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::dump"); + ACE_TSS_Guard<LOCK>::dump (); +} + +template <class LOCK> +ACE_TSS_Read_Guard<LOCK>::ACE_TSS_Read_Guard (LOCK &lock, int block) +{ +// ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::ACE_TSS_Read_Guard"); + + this->init_key (); + ACE_Guard<LOCK> *guard; + ACE_NEW (guard, ACE_Read_Guard<LOCK> (lock, block)); + ACE_Thread::setspecific (this->key_, (void *) guard); +} + +template <class LOCK> int +ACE_TSS_Read_Guard<LOCK>::acquire (void) +{ +// ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::acquire"); + + ACE_Read_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->acquire_read (); +} + +template <class LOCK> int +ACE_TSS_Read_Guard<LOCK>::tryacquire (void) +{ +// ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::tryacquire"); + + ACE_Read_Guard<LOCK> *guard = 0; + ACE_Thread::getspecific (this->key_, (void **) &guard); + return guard->tryacquire_read (); +} + +template <class LOCK> int +ACE_TSS_Read_Guard<LOCK>::acquire_read (void) +{ +// ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::acquire_read"); + + return this->acquire (); +} + +template <class LOCK> int +ACE_TSS_Read_Guard<LOCK>::tryacquire_read (void) +{ +// ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::tryacquire_read"); + + return this->tryacquire (); +} + +template <class LOCK> void +ACE_TSS_Read_Guard<LOCK>::dump (void) const +{ +// ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::dump"); + ACE_TSS_Guard<LOCK>::dump (); +} + +#endif /* defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) */ +#endif /* ACE_SYNCH_T_C */ diff --git a/ace/Synch_T.h b/ace/Synch_T.h new file mode 100644 index 00000000000..ffa705c0f70 --- /dev/null +++ b/ace/Synch_T.h @@ -0,0 +1,613 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Synch_T.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_SYNCH_T_H) +#define ACE_SYNCH_T_H + +#include "ace/Event_Handler.h" +#include "ace/Synch.h" + +// Forward decl +class ACE_Time_Value; + +template <class LOCK, class TYPE> +class ACE_Test_and_Set : public ACE_Event_Handler +{ + // = TITLE + // Implements the classic ``test and set'' operation. + // + // = DESCRIPTION + // This class keeps track of the status of <is_set_>, which can + // be set based on various events (such as receipt of a signal). +public: + ACE_Test_and_Set (TYPE initial_value = 0); + + TYPE is_set (void) const; + // Returns true if we are set, else false. + + TYPE set (TYPE); + // Sets the <set_> status, returning + + virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0); + // Called when object is signaled by OS (either via UNIX signals or + // when a Win32 object becomes signaled). + +private: + TYPE is_set_; + // Keeps track of our state. + + LOCK lock_; +}; + +template <class LOCK, class TYPE> +class ACE_Atomic_Op + // = TITLE + // Transparently parameterizes synchronization into basic + // arithmetic operations. + // + // = DESCRIPTION + // This class is described in an article in the July/August 1994 + // issue of the C++ Report magazine. It implements a + // templatized version of the Decorator pattern from the GoF book. +{ +public: + ACE_Atomic_Op (void); + // Initialize <count_> to 0. + + ACE_Atomic_Op (TYPE c); + // Initialize <count_> to c. + + TYPE operator++ (void); + // Atomically pre-increment <count_>. + + TYPE operator++ (int); + // Atomically post-increment <count_>. + + TYPE operator+= (const TYPE i); + // Atomically increment <count_> by inc. + + TYPE operator-- (void); + // Atomically pre-decrement <count_>. + + TYPE operator-- (int); + // Atomically post-decrement <count_>. + + TYPE operator-= (const TYPE i); + // Atomically decrement <count_> by dec. + + TYPE operator== (const TYPE i) const; + // Atomically compare <count_> with rhs. + + TYPE operator>= (const TYPE i) const; + // Atomically check if <count_> greater than or equal to rhs. + + TYPE operator> (const TYPE rhs) const; + // Atomically check if <count_> greater than rhs. + + TYPE operator<= (const TYPE rhs) const; + // Atomically check if <count_> less than or equal to rhs. + + TYPE operator< (const TYPE rhs) const; + // Atomically check if <count_> less than rhs. + + void operator= (const TYPE i); + // Atomically assign rhs to <count_>. + + void operator= (const ACE_Atomic_Op<LOCK, TYPE> &rhs); + // Atomically assign <rhs> to <count_>. + + operator TYPE () const; + // Atomically return <count_>. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + ACE_Atomic_Op (const ACE_Atomic_Op<LOCK, TYPE> &); + // Manage copying... + +private: + LOCK lock_; + // Type of synchronization mechanism. + + TYPE value_; + // Current object decorated by the atomic op. +}; + +template <class TYPE> +class ACE_TSS + // = TITLE + // Allows objects that are "physically" in thread specific + // storage (i.e., private to a thread) to be accessed as though + // they were "logically" global to a program. + // + // = DESCRIPTION + // This class is a wrapper around the OS thread library + // thread-specific functions. It uses the C++ operator->() to + // shield applications from the details of accessing + // thread-specific storage. +{ +public: + ACE_TSS (TYPE *ts_obj = 0); + // If caller has passed us a non-NULL ts_obj *, then we'll just use + // this to initialize the thread-specific value. Thus, subsequent + // calls to operator->() will return this value. This is useful + // since it enables us to assign objects to thread-specific data + // that have arbitrarily complex constructors! + + ~ACE_TSS (void); + // Deregister with thread-key administration. + + TYPE *ts_object (void) const; + // Get the thread-specific object for the key associated with this + // object. Returns 0 if the data has never been initialized, + // otherwise returns a pointer to the data. + + TYPE *ts_object (TYPE *); + // Set the thread-specific object for the key associated with this + // object. Returns 0 if the data has never been initialized, + // otherwise returns a pointer to the previous value for the data. + + TYPE *operator-> () const; + // Use a "smart pointer" to get the thread-specific object + // associated with the <key_>. + + operator TYPE *(void) const; + // return or create and return the calling threads TYPE object. + + virtual TYPE *make_TSS_TYPE (void) const; + // hook for construction parameters. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + TYPE *ts_get (void) const; + // Actually implements the code that retrieves the object from + // thread-specific storage. + +#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) + TYPE type_; + // This implementation only works for non-threading systems... +#else + ACE_Mutex keylock_; + // Avoid race conditions during initialization. + + int once_; + // "First time in" flag. + + ACE_thread_key_t key_; + // Key for the thread-specific error data. + + static void cleanup (void *ptr); + // "Destructor" that deletes internal TYPE * when thread exits. +#endif /* defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) */ + // = Disallow copying... + void operator= (const ACE_TSS<TYPE> &) {} + ACE_TSS (const ACE_TSS<TYPE> &) {} +}; + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +class ACE_NULL_SYNCH + // = TITLE + // Implement a do nothing Synchronization wrapper that + // typedefs the <ACE_Condition> and <ACE_Mutex> to the Null* versions. +{ +public: + typedef ACE_Null_Mutex MUTEX; + // "Do-nothing" mutex type. + + typedef ACE_Null_Condition_Mutex CONDITION; + // "Do-nothing" condition type. +}; +#else /* Necessary to support broken cfront-based C++ compilers... */ +#define ACE_NULL_SYNCH ACE_Null_Mutex, ACE_Null_Condition_Mutex +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + +template <class LOCK> +class ACE_Guard + // = TITLE + // This data structure is meant to be used within a method or + // function... It performs automatic aquisition and release of + // a parameterized synchronization object <LOCK>. + // + // = DESCRIPTION + // The <LOCK> class given as an actual parameter must provide at + // the very least the <acquire>, <tryacquire>, <release>, and + // <remove> methods. +{ +public: + ACE_Guard (LOCK &l, int block = 1): lock_ (&l) + { + this->owner_ = block ? this->acquire () : this->tryacquire (); + } + // Implicitly and automatically acquire (or try to acquire) the + // lock. + + ~ACE_Guard (void) { if (this->owner_ != -1) this->release (); } + // Implicitly release the lock. + + int locked (void) { return this->owner_ != -1; } + // 1 if locked, 0 if couldn't acquire the lock + // (errno will contain the reason for this). + + int remove (void) { return this->release (); } + // Explicitly release the lock. + + int acquire (void) { return this->owner_ = this->lock_->acquire (); } + // Explicitly acquire the lock. + + int tryacquire (void) { return this->owner_ = this->lock_->tryacquire (); } + // Conditionally acquire the lock (i.e., won't block). + + int release (void) { this->owner_ = -1; return this->lock_->release (); } + // Explicitly release the lock. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_Guard (LOCK *lock): lock_ (lock) {} + // Helper, meant for subclass only. + + LOCK *lock_; + // Pointer to the LOCK we're guarding. + + int owner_; + // Keeps track of whether we acquired the lock or failed. + +private: + // = Prevent assignment and initialization. + void operator= (const ACE_Guard<LOCK> &) {} + ACE_Guard (const ACE_Guard<LOCK> &) {} +}; + +template <class LOCK> +class ACE_Write_Guard : public ACE_Guard<LOCK> + // = TITLE + // This class is similar to class <ACE_Guard>, though it + // acquires/releases a write lock automatically (naturally, the + // <LOCK> it is instantiated with must support the appropriate + // API). +{ +public: + ACE_Write_Guard (LOCK &m, int block = 1): ACE_Guard<LOCK> (&m) + { + this->owner_ = block ? this->acquire_write () : this->tryacquire_write (); + } + // Implicitly and automatically acquire (or try to acquire) a write + // lock. + + int acquire_write (void) { return this->owner_ = this->lock_->acquire_write (); } + // Explicitly acquire the write lock. + + int acquire (void) { return this->owner_ = this->lock_->acquire_write (); } + // Explicitly acquire the write lock. + + int tryacquire_write (void) { return this->owner_ = this->lock_->acquire_write (); } + // Conditionally acquire the write lock (i.e., won't block). + + int tryacquire (void) { return this->owner_ = this->lock_->tryacquire_write (); } + // Conditionally acquire the write lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class LOCK> +class ACE_Read_Guard : public ACE_Guard<LOCK> + // = TITLE + // This class is similar to class <ACE_Guard>, though it + // acquires/releases a read lock automatically (naturally, the + // <LOCK> it is instantiated with must support the appropriate + // API). +{ +public: + ACE_Read_Guard (LOCK &m, int block = 1): ACE_Guard<LOCK> (&m) + { + this->owner_ = block ? this->acquire_read () : this->tryacquire_read (); + } + // Implicitly and automatically acquire (or try to acquire) a read + // lock. + + int acquire_read (void) { return this->owner_ = this->lock_->acquire_read (); } + // Explicitly acquire the read lock. + + int acquire (void) { return this->owner_ = this->lock_->acquire_read (); } + // Explicitly acquire the read lock. + + int tryacquire_read (void) { return this->owner_ = this->lock_->tryacquire_read (); } + // Conditionally acquire the read lock (i.e., won't block). + + int tryacquire (void) { return this->owner_ = this->lock_->tryacquire_read (); } + // Conditionally acquire the read lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) + +#define ACE_TSS_Guard ACE_Guard +#define ACE_TSS_Write_GUARD ACE_Write_Guard +#define ACE_TSS_Read_GUARD ACE_Read_Guard + +#else // ACE platform supports some form of threading and + // thread-specific storage. + +template <class LOCK> +class ACE_TSS_Guard + // = TITLE + // This data structure is meant to be used within a method or + // function... It performs automatic aquisition and release of + // a synchronization object. Moreover, it ensures that the lock + // is released even if a thread exits via "thr_exit()"! +{ +public: + ACE_TSS_Guard (LOCK &lock, int block = 1); + // Implicitly and automatically acquire the thread-specific lock. + + ~ACE_TSS_Guard (void); + // Implicitly release the thread-specific lock. + + int remove (void); + // Explicitly release the thread-specific lock. + + int acquire (void); + // Explicitly acquire the thread-specific lock. + + int tryacquire (void); + // Conditionally acquire the thread-specific lock (i.e., won't + // block). + + int release (void); + // Explicitly release the thread-specific lock. + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + ACE_TSS_Guard (void); + // Helper, meant for subclass only. + + void init_key (void); + // Initialize the key. + + static void cleanup (void *ptr); + // Called when thread exits to clean up the lock. + + ACE_thread_key_t key_; + // Thread-specific key... + +private: + // = Prevent assignment and initialization. + void operator= (const ACE_TSS_Guard<LOCK> &) {} + ACE_TSS_Guard (const ACE_TSS_Guard<LOCK> &) {} +}; + +template <class LOCK> +class ACE_TSS_Write_Guard : public ACE_TSS_Guard<LOCK> + // = TITLE + // This class is similar to class ACE_TSS_Guard, though it + // acquires/releases a write-lock automatically (naturally, the + // LOCK it is instantiated with must support the appropriate + // API). +{ +public: + ACE_TSS_Write_Guard (LOCK &lock, int block = 1); + // Implicitly and automatically acquire the thread-specific write lock. + + int acquire_write (void); + // Explicitly acquire the thread-specific write lock. + + int acquire (void); + // Explicitly acquire the thread-specific write lock. + + int tryacquire_write (void); + // Conditionally acquire the thread-specific write lock (i.e., won't block). + + int tryacquire (void); + // Conditionally acquire the thread-specific write lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class LOCK> +class ACE_TSS_Read_Guard : public ACE_TSS_Guard<LOCK> + // = TITLE + // This class is similar to class <ACE_TSS_Guard>, though it + // acquires/releases a read lock automatically (naturally, the + // <LOCK> it is instantiated with must support the appropriate + // API). +{ +public: + ACE_TSS_Read_Guard (LOCK &lock, int block = 1); + // Implicitly and automatically acquire the thread-specific read lock. + + int acquire_read (void); + // Explicitly acquire the thread-specific read lock. + + int acquire (void); + // Explicitly acquire the thread-specific read lock. + + int tryacquire_read (void); + // Conditionally acquire the thread-specific read lock (i.e., won't block). + + int tryacquire (void); + // Conditionally acquire the thread-specific read lock (i.e., won't block). + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; +#endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */ + +#if defined (ACE_HAS_THREADS) // ACE platform supports some form of threading. + +template <class MUTEX> +class ACE_Condition + // = TITLE + // ACE_Condition variable wrapper, which allows threads to block + // until shared data changes state. +{ +public: + ACE_Condition (MUTEX &m, int type = USYNC_THREAD, + LPCTSTR name = 0, void *arg = 0); + // Initialize the condition variable. + + ~ACE_Condition (void); + // Implicitly destroy the condition variable. + + int remove (void); + // Explicitly destroy the condition variable. + + int wait (const ACE_Time_Value *abstime); + // Block on condition, or until absolute time-of-day has passed. If + // abstime == 0 use "blocking" <wait> semantics. Else, if <abstime> + // != 0 and the call times out before the condition is signaled + // <wait> returns -1 and sets errno to ETIME. + + int wait (void); + // Block on condition. + + int wait (MUTEX &mutex, const ACE_Time_Value *abstime = 0); + // Block on condition or until absolute time-of-day has passed. If + // abstime == 0 use "blocking" wait() semantics on the <mutex> + // passed as a parameter (this is useful if you need to store the + // <Condition> in shared memory). Else, if <abstime> != 0 and the + // call times out before the condition is signaled <wait> returns -1 + // and sets errno to ETIME. + + int signal (void); + // Signal one waiting thread. + + int broadcast (void); + // Signal *all* waiting threads. + + MUTEX &mutex (void); + // Returns a reference to the underlying mutex_; + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_cond_t cond_; + // Condition variable. + + MUTEX &mutex_; + // Reference to mutex lock. + + // = Prevent assignment and initialization. + void operator= (const ACE_Condition<MUTEX> &) {} + ACE_Condition (const ACE_Condition<MUTEX> &c): mutex_ (c.mutex_) {} +}; + +template <class MUTEX> +class ACE_Process_Condition : public ACE_Condition<MUTEX> + // = TITLE + // ACE_Condition variable wrapper that works across processes. +{ +public: + ACE_Process_Condition (MUTEX &m, LPCTSTR name = 0, void *arg = 0); + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template <class MUTEX> +class ACE_Thread_Condition : public ACE_Condition<MUTEX> + // = TITLE + // ACE_Condition variable wrapper that works within processes. +{ +public: + ACE_Thread_Condition (MUTEX &m, LPCTSTR name = 0, void *arg = 0); + + void dump (void) const; + // Dump the state of an object. + + // ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#if defined (ACE_HAS_TEMPLATE_TYPEDEFS) +class ACE_MT_SYNCH + // = TITLE + // Implement a default thread safe synchronization wrapper that + // typedefs the <ACE_Condition> and <ACE_Mutex> to the + // <ACE_Condition> and <ACE_Mutex> versions. Note that this + // should be a template, but SunC++ 4.0.1 complains about + // this... +{ +public: + typedef ACE_Thread_Mutex MUTEX; + typedef ACE_Condition_Thread_Mutex CONDITION; +}; +#else /* Necessary to support broken cfront-based C++ compilers... */ +#define ACE_MT_SYNCH ACE_Thread_Mutex,ACE_Condition_Thread_Mutex +#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + +#if defined (__osf__) && ! defined (__GNUG__) +#pragma define_template ACE_Condition <ACE_Mutex> +#endif + +#define ACE_SYNCH ACE_MT_SYNCH +#else +#define ACE_SYNCH ACE_NULL_SYNCH +#endif /* ACE_HAS_THREADS */ + +#if defined (__ACE_INLINE__) +#include "ace/Synch_T.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Synch_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Synch_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_SYNCH_T_H */ diff --git a/ace/Synch_T.i b/ace/Synch_T.i new file mode 100644 index 00000000000..cdc6646d889 --- /dev/null +++ b/ace/Synch_T.i @@ -0,0 +1,176 @@ +/* -*- C++ -*- */ +// $Id$ + +// Synch_T.i + +#include "ace/Thread.h" + +template <class LOCK, class TYPE> ACE_INLINE +ACE_Atomic_Op<LOCK, TYPE>::ACE_Atomic_Op (const ACE_Atomic_Op<LOCK, TYPE> &rhs) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::ACE_Atomic_Op"); + *this = rhs; // Invoke the assignment operator. +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator++ (void) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator++"); + ACE_Guard<LOCK> m (this->lock_); + return ++this->value_; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator++ (int) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator++"); + ACE_Guard<LOCK> m (this->lock_); + return this->value_++; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator+= (const TYPE i) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator+="); + ACE_Guard<LOCK> m (this->lock_); + return this->value_ += i; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator-- (void) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator--"); + ACE_Guard<LOCK> m (this->lock_); + return --this->value_; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator-- (int) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator--"); + ACE_Guard<LOCK> m (this->lock_); + return this->value_--; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator-= (const TYPE i) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator-="); + ACE_Guard<LOCK> m (this->lock_); + return this->value_ -= i; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator== (const TYPE i) const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator=="); + ACE_Guard<LOCK> m ((LOCK &) this->lock_); + return this->value_ == i; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator>= (const TYPE i) const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator>="); + ACE_Guard<LOCK> m ((LOCK &) this->lock_); + return this->value_ >= i; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator> (const TYPE rhs) const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator>"); + ACE_Guard<LOCK> m ((LOCK &) this->lock_); + return this->value_ > rhs; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator<= (const TYPE rhs) const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator<="); + ACE_Guard<LOCK> m ((LOCK &) this->lock_); + return this->value_ <= rhs; +} + +template <class LOCK, class TYPE> ACE_INLINE TYPE +ACE_Atomic_Op<LOCK, TYPE>::operator< (const TYPE rhs) const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator<"); + ACE_Guard<LOCK> m ((LOCK &) this->lock_); + return this->value_ < rhs; +} + +template <class LOCK, class TYPE> void +ACE_Atomic_Op<LOCK, TYPE>::operator= (const ACE_Atomic_Op<LOCK, TYPE> &rhs) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator="); + if (&rhs == this) + return; // Avoid deadlock... + ACE_Guard<LOCK> m (this->lock_); + // This will call ACE_Atomic_Op::TYPE(), which will ensure the value + // of <rhs> is acquired atomically. + this->value_ = rhs; +} + +template <class LOCK, class TYPE> ACE_INLINE +ACE_Atomic_Op<LOCK, TYPE>::operator TYPE () const +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator TYPE"); + ACE_Guard<LOCK> m ((LOCK &) this->lock_); + return this->value_; +} + +template <class LOCK, class TYPE> ACE_INLINE void +ACE_Atomic_Op<LOCK, TYPE>::operator= (const TYPE i) +{ +// ACE_TRACE ("ACE_Atomic_Op<LOCK, TYPE>::operator="); + ACE_Guard<LOCK> m (this->lock_); + this->value_ = i; +} +#if defined (ACE_HAS_THREADS) + +template<class MUTEX> ACE_INLINE int +ACE_Condition<MUTEX>::remove (void) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::remove"); + + // cond_destroy() is called in a loop if the condition variable is + // BUSY. This avoids a condition where a condition is signaled and + // because of some timing problem, the thread that is to be signaled + // has called the cond_wait routine after the signal call. Since + // the condition signal is not queued in any way, deadlock occurs. + + int result = 0; + + while ((result = ACE_OS::cond_destroy (&this->cond_)) == -1 + && errno == EBUSY) + { + ACE_OS::cond_broadcast (&this->cond_); + ACE_OS::thr_yield (); + } + + return result; +} + +template<class MUTEX> ACE_INLINE MUTEX & +ACE_Condition<MUTEX>::mutex (void) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::mutex"); + return this->mutex_; +} + +template <class MUTEX> ACE_INLINE int +ACE_Condition<MUTEX>::signal (void) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::signal"); + return ACE_OS::cond_signal (&this->cond_); +} + +template <class MUTEX> ACE_INLINE int +ACE_Condition<MUTEX>::broadcast (void) +{ +// ACE_TRACE ("ACE_Condition<MUTEX>::broadcast"); + return ACE_OS::cond_broadcast (&this->cond_); +} +#endif /* ACE_HAS_THREADS */ + diff --git a/ace/System_Time.cpp b/ace/System_Time.cpp new file mode 100644 index 00000000000..14a13a9939f --- /dev/null +++ b/ace/System_Time.cpp @@ -0,0 +1,86 @@ +// System_Time.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Time_Value.h" +#include "ace/System_Time.h" + +ACE_System_Time::ACE_System_Time (const char *poolname) +: delta_time_ (0) +{ + ACE_TRACE ("ACE_System_Time::ACE_System_Time"); + ACE_NEW (this->shmem_, ALLOCATOR (poolname)); +} + +ACE_System_Time::~ACE_System_Time (void) +{ + delete this->shmem_; + ACE_TRACE ("ACE_System_Time::~ACE_System_Time"); +} + +// Get the local system time. + +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; + return 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 + void * temp; + if (this->shmem_->find (ACE_DEFAULT_TIME_SERVER_STR, temp) == -1) + { + // No time entry in shared memory (meaning no Clerk exists) + // so return the local time of the host. + return this->get_local_system_time (time_out); + } + else + { + // 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 + // ahead of our local clock so add delta to the local time to get an + // approximation of the system time. Else if delta time is negative, + // it means that our local clock is ahead of the system clock, so + // return the last local time stored (to avoid time conflicts). + if (*this->delta_time_ >=0 ) + { + this->get_local_system_time (local_time); + time_out = local_time + (ACE_UINT32) *this->delta_time_; + } + else + // Return the last local time. Note that this is stored as the + // second field in shared memory. + time_out = *(this->delta_time_ + 1); + return 0; +} + +// Synchronize local system time with the central time server using +// specified mode. + +int +ACE_System_Time::sync_local_system_time (ACE_System_Time::Sync_Mode mode) +{ + ACE_TRACE ("ACE_System_Time::sync_local_system_time"); + return 0; +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Malloc<ACE_MMAP_Memory_Pool, ACE_Null_Mutex>; +template class ACE_Allocator_Adapter<ACE_Malloc<ACE_MMAP_Memory_Pool, ACE_Null_Mutex> >; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/System_Time.h b/ace/System_Time.h new file mode 100644 index 00000000000..c8c1035fe03 --- /dev/null +++ b/ace/System_Time.h @@ -0,0 +1,73 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// System_Time.h +// +// = AUTHOR +// Prashant Jain, Tim H. Harrison and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_SYSTEM_TIME_H) +#define ACE_SYSTEM_TIME_H + +#include "ace/OS.h" +#include "ace/Malloc.h" + +class ACE_Export ACE_Date_Time + // TITLE + // This class holds internally date and time and has interfaces + // for getting month or compares of times and dates, etc. +{ +public: +}; + +class ACE_Export ACE_System_Time + // = TITLE + // Defines the timer services of the OS interface to access the + // system time either on the local host or on the central time + // server in the network. +{ +public: + enum Sync_Mode { Jump, Adjust }; + // enumeration types to specify mode of synchronization with master + // clock. Jump will set local system time directly (thus possibly + // producing time gaps or ambiguous local system times. Adjust will + // smoothly slow down or speed up the local system clock to reach + // the system time of the master clock. + + ACE_System_Time (const char *poolname = ACE_DEFAULT_BACKING_STORE); + // Default constructor. + + ~ACE_System_Time (void); + // Default destructor. + + int get_local_system_time (ACE_UINT32 &time_out); + // Get the local system time. + + int get_master_system_time (ACE_UINT32 &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. + +private: + typedef ACE_Malloc <ACE_MMAP_Memory_Pool, ACE_Null_Mutex> MALLOC; + typedef ACE_Allocator_Adapter<MALLOC> ALLOCATOR; + + ALLOCATOR *shmem_; + // Our allocator (used for obtaining system time from shared memory). + + long *delta_time_; + // Pointer to delta time kept in shared memory. +}; + +#endif /* ACE_SYSTEM_TIME_H */ diff --git a/ace/TLI.cpp b/ace/TLI.cpp new file mode 100644 index 00000000000..d7724a87f6a --- /dev/null +++ b/ace/TLI.cpp @@ -0,0 +1,172 @@ +// TLI.cpp +// $Id$ + +/* Defines the member functions for the base class of the ACE_TLI + abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/TLI.h" +#include "ace/Log_Msg.h" + +#if defined (ACE_HAS_TLI) + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI) + +void +ACE_TLI::dump (void) const +{ + ACE_TRACE ("ACE_TLI::dump"); +} + +ACE_TLI::ACE_TLI (void) +{ + ACE_TRACE ("ACE_TLI::ACE_TLI"); +#if defined (ACE_HAS_SVR4_TLI) +// Solaris 2.4 ACE_TLI option handling is broken. Thus, we must do +// the memory allocation ourselves... Thanks to John P. Hearn +// (jph@ccrl.nj.nec.com) for the help. + + this->so_opt_req.opt.maxlen = sizeof (opthdr) + sizeof (long); + ACE_NEW (this->so_opt_req.opt.buf, char[this->so_opt_req.opt.maxlen]); + + this->so_opt_ret.opt.maxlen = sizeof (opthdr) + sizeof (long); + this->so_opt_ret.opt.buf = new char[this->so_opt_ret.opt.maxlen]; + + if (this->so_opt_ret.opt.buf == 0) + { + delete [] this->so_opt_req.opt.buf; + this->so_opt_req.opt.buf = 0; + return; + } +#endif /* ACE_HAS_SVR4_TLI */ +} + +ACE_HANDLE +ACE_TLI::open (const char device[], int oflag, struct t_info *info) +{ + ACE_TRACE ("ACE_TLI::open"); + if (oflag == 0) + oflag = O_RDWR; + this->set_handle (ACE_OS::t_open ((char *) device, oflag, info)); + + return this->get_handle (); +} + +ACE_TLI::~ACE_TLI (void) +{ + ACE_TRACE ("ACE_TLI::~ACE_TLI"); +#if defined (ACE_HAS_SVR4_TLI) + if (this->so_opt_req.opt.buf) + { + delete [] this->so_opt_req.opt.buf; + delete [] this->so_opt_ret.opt.buf; + this->so_opt_req.opt.buf = 0; + this->so_opt_ret.opt.buf = 0; + } +#endif /* ACE_HAS_SVR4_TLI */ +} + +ACE_TLI::ACE_TLI (const char device[], int oflag, struct t_info *info) +{ + ACE_TRACE ("ACE_TLI::ACE_TLI"); + if (this->open (device, oflag, info) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_TLI::ACE_TLI")); +} + +int +ACE_TLI::get_local_addr (ACE_Addr &sa) const +{ + ACE_TRACE ("ACE_TLI::get_local_addr"); +#if defined (ACE_HAS_SVR4_TLI) + struct netbuf name; + + name.maxlen = sa.get_size (); + name.buf = (char *) sa.get_addr (); + + if (ACE_OS::ioctl (this->get_handle (), TI_GETMYNAME, &name) == -1) +/* if (ACE_OS::t_getname (this->get_handle (), &name, LOCALNAME) == -1) */ +#else /* SunOS4 sucks... */ + if (0) +#endif /* ACE_HAS_SVR4_TLI */ + return -1; + else + return 0; +} + +int +ACE_TLI::close (void) +{ + ACE_TRACE ("ACE_TLI::close"); + ACE_HANDLE result = 0; + + if (this->get_handle () != ACE_INVALID_HANDLE) + { + result = ACE_OS::t_close (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + } + return result; +} + +int +ACE_TLI::set_option (int level, int option, void *optval, int optlen) +{ + ACE_TRACE ("ACE_TLI::set_option"); +#if defined (ACE_HAS_SVR4_TLI) + /* Set up options for ACE_TLI */ + + struct opthdr *opthdr = 0; /* See <sys/socket.h> for details on this format */ + + this->so_opt_req.flags = T_NEGOTIATE; + this->so_opt_req.opt.len = sizeof *opthdr + OPTLEN (optlen); + + if (this->so_opt_req.opt.len > this->so_opt_req.opt.maxlen) + { + t_errno = TBUFOVFLW; + return -1; + } + + opthdr = (struct opthdr *) this->so_opt_req.opt.buf; + opthdr->level = level; + opthdr->name = option; + opthdr->len = OPTLEN (optlen); + ACE_OS::memcpy (OPTVAL (opthdr), optval, optlen); + + return ACE_OS::t_optmgmt (this->get_handle (), &this->so_opt_req, &this->so_opt_ret); +#else + return -1; +#endif /* ACE_HAS_SVR4_TLI */ +} + +int +ACE_TLI::get_option (int level, int option, void *optval, int &optlen) +{ + ACE_TRACE ("ACE_TLI::get_option"); +#if defined (ACE_HAS_SVR4_TLI) + struct opthdr *opthdr = 0; /* See <sys/socket.h> for details on this format */ + + this->so_opt_req.flags = T_CHECK; + this->so_opt_ret.opt.len = sizeof *opthdr + OPTLEN (optlen); + + if (this->so_opt_ret.opt.len > this->so_opt_ret.opt.maxlen) + { + t_errno = TBUFOVFLW; + return -1; + } + + opthdr = (struct opthdr *) this->so_opt_req.opt.buf; + opthdr->level = level; + opthdr->name = option; + opthdr->len = OPTLEN (optlen); + if (ACE_OS::t_optmgmt (this->get_handle (), &this->so_opt_req, &this->so_opt_ret) == -1) + return -1; + else + { + ACE_OS::memcpy (optval, OPTVAL (opthdr), optlen); + return 0; + } +#else + return -1; +#endif /* ACE_HAS_SVR4_TLI */ +} + +#endif /* ACE_HAS_TLI */ diff --git a/ace/TLI.h b/ace/TLI.h new file mode 100644 index 00000000000..0584a5b0c60 --- /dev/null +++ b/ace/TLI.h @@ -0,0 +1,98 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// TLI.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TLI_H) +#define ACE_TLI_H + +#include "ace/IPC_SAP.h" +#include "ace/Addr.h" + +// 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) +#define ACE_TLI_ACCEPTOR ACE_TLI_Acceptor +#define ACE_TLI_CONNECTOR ACE_TLI_Connector +#define ACE_TLI_STREAM ACE_TLI_Stream +#else /* TEMPLATES are broken (must be a cfront-based compiler...) */ +#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 +#endif /* ACE_TEMPLATE_TYPEDEFS */ + +#if defined (ACE_HAS_TLI) +class ACE_Export ACE_TLI : public ACE_IPC_SAP + // = TITLE + // Defines the member functions for the base class of the + // ACE_TLI abstraction. +{ +public: + // = Initialization and termination methods. + ACE_HANDLE open (const char device[], + int oflag = O_RDWR, + struct t_info *info = 0); + // Initialize a TLI endpoint. + + int close (void); + // Close a TLI endpoint and release resources. + + int set_option (int level, int option, void *optval, int optlen); + // Set underlying protocol options. + + int get_option (int level, int option, void *optval, int &optlen); + // Get underlying protocol options. + + // = Calls to underlying TLI operations. + int look (void) const; + int rcvdis (struct t_discon * = 0) const; + int snddis (struct t_call * = 0) const; + int sndrel (void) const; + int rcvrel (void) const; + + int get_local_addr (ACE_Addr &) const; + // Return our local endpoint address. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + // = Ensure we are an abstract class. + ACE_TLI (void); + // Default constructor. + ~ACE_TLI (void); + // Destructor. + + ACE_TLI (const char device[], int oflag = O_RDWR, struct t_info *info = 0); + // Initialize a TLI endpoint. + +private: +#if defined (ACE_HAS_SVR4_TLI) + // Insane TLI option management. + struct t_optmgmt so_opt_req; + struct t_optmgmt so_opt_ret; +#endif /* ACE_HAS_SVR4_TLI */ +}; + +#include "ace/TLI.i" + +#endif /* ACE_HAS_TLI */ +#endif /* ACE_TLI_H */ diff --git a/ace/TLI.i b/ace/TLI.i new file mode 100644 index 00000000000..349f9d1fc74 --- /dev/null +++ b/ace/TLI.i @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ +// $Id$ + +// TLI.i + +#include "ace/TLI.h" + +inline int +ACE_TLI::look (void) const +{ + ACE_TRACE ("ACE_TLI::look"); + return ACE_OS::t_look (this->get_handle ()); +} + +inline int +ACE_TLI::rcvdis (struct t_discon *discon) const +{ + ACE_TRACE ("ACE_TLI::rcvdis"); + return ACE_OS::t_rcvdis (this->get_handle (), discon); +} + +inline int +ACE_TLI::snddis (struct t_call *call) const +{ + ACE_TRACE ("ACE_TLI::snddis"); + return ACE_OS::t_snddis (this->get_handle (), call); +} + +inline int +ACE_TLI::rcvrel (void) const +{ + ACE_TRACE ("ACE_TLI::rcvrel"); + return ACE_OS::t_rcvrel (this->get_handle ()); +} + +inline int +ACE_TLI::sndrel (void) const +{ + ACE_TRACE ("ACE_TLI::sndrel"); + return ACE_OS::t_sndrel (this->get_handle ()); +} diff --git a/ace/TLI_Acceptor.cpp b/ace/TLI_Acceptor.cpp new file mode 100644 index 00000000000..4fce1af33d2 --- /dev/null +++ b/ace/TLI_Acceptor.cpp @@ -0,0 +1,456 @@ +// TLI_Acceptor.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/TLI_Acceptor.h" +#include "ace/Log_Msg.h" + +#if defined (ACE_HAS_TLI) + +// Put the actual definitions of the ACE_TLI_Request and +// ACE_TLI_Request_Queue classes here to hide them from clients... + +struct ACE_TLI_Request +{ + struct t_call *callp_; + ACE_HANDLE handle_; + ACE_TLI_Request *next_; +}; + +class ACE_TLI_Request_Queue +{ +public: + ACE_TLI_Request_Queue (void); + + int open (int fd, int size); + int close (void); + + int enqueue (const char device[], int restart, int rwflag); + int dequeue (ACE_TLI_Request *&ptr); + int remove (int sequence_number); + + int is_empty (void) const; + int is_full (void) const; + + ACE_TLI_Request *alloc (void); + void free (ACE_TLI_Request *node); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int handle_; + int size_; + int current_count_; + ACE_TLI_Request *base_; + ACE_TLI_Request *tail_; + ACE_TLI_Request *free_list_; +}; + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue) + +void +ACE_TLI_Request_Queue::dump (void) const +{ + ACE_TRACE ("ACE_TLI_Request_Queue::dump"); +} + +int +ACE_TLI_Request_Queue::is_empty (void) const +{ + ACE_TRACE ("ACE_TLI_Request_Queue::is_empty"); + return this->current_count_ == 0; +} + +int +ACE_TLI_Request_Queue::is_full (void) const +{ + ACE_TRACE ("ACE_TLI_Request_Queue::is_full"); + return this->current_count_ + 1 == this->size_; // Add 1 for the dummy. +} + +// Add a node to the free list stack. + +void +ACE_TLI_Request_Queue::free (ACE_TLI_Request *node) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::free"); + node->next_ = this->free_list_; + this->free_list_ = node; +} + +// Remove a node from the free list stack. + +ACE_TLI_Request * +ACE_TLI_Request_Queue::alloc (void) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::alloc"); + ACE_TLI_Request *temp = this->free_list_; + this->free_list_ = this->free_list_->next_; + return temp; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor) + +void +ACE_TLI_Acceptor::dump (void) const +{ + ACE_TRACE ("ACE_TLI_Acceptor::dump"); +} + +ACE_TLI_Acceptor::ACE_TLI_Acceptor (void) + : queue_ (0) +{ + ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor"); +} + +int +ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request *&ptr) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::dequeue"); + ptr = this->tail_->next_; + this->tail_->next_ = ptr->next_; + this->current_count_--; + return 0; +} + +// This is hideous... + +static ACE_HANDLE +open_new_endpoint (ACE_HANDLE listen_handle, const char dev[], + struct t_call *callp, int rwf) +{ + ACE_TRACE ("open_new_endpoint"); + ACE_HANDLE fd; + + if ((fd = ACE_OS::t_open ((char *) dev, O_RDWR, 0)) == ACE_INVALID_HANDLE + || ACE_OS::t_bind (fd, 0, 0) == ACE_INVALID_HANDLE) + fd = ACE_INVALID_HANDLE; +#if defined (I_PUSH) + else if (rwf != 0 && ACE_OS::ioctl (fd, I_PUSH, "tirdwr") == ACE_INVALID_HANDLE) + fd = ACE_INVALID_HANDLE; +#endif /* I_PUSH */ + + if (fd == ACE_INVALID_HANDLE) + ACE_OS::t_snddis (listen_handle, callp); + return fd; +} + +// Close down the acceptor and release resources. + +ACE_INLINE int +ACE_TLI_Request_Queue::close (void) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::close"); + int res = 0; + + for (int i = 0; i < this->size_; i++) + { + ACE_TLI_Request &item = this->base_[i]; + + item.handle_ = ACE_INVALID_HANDLE; + if (ACE_OS::t_free ((char *) item.callp_, T_CALL) != 0) + res = ACE_INVALID_HANDLE; + } + delete [] this->base_; + this->base_ = 0; + return res; +} + +ACE_HANDLE +ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::open"); + this->handle_ = f; + this->size_ = sz + 1; // Add one more for the dummy node. + + ACE_NEW_RETURN (this->base_, ACE_TLI_Request[this->size_], ACE_INVALID_HANDLE); + + // Initialize the ACE_Queue and the free list. + + for (int i = 0; i < this->size_; i++) + { + ACE_TLI_Request *item = &this->base_[i]; + this->free (item); + + item->handle_ = ACE_INVALID_HANDLE; + item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_, T_CALL, T_ALL); + + if (item->callp_ == 0) + return ACE_INVALID_HANDLE; + } + + this->tail_ = this->alloc (); + this->tail_->next_ = this->tail_; + return 0; +} + +ACE_INLINE +ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void) + : size_ (0), + current_count_ (0), + base_ (0), + tail_ (0), + free_list_ (0) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue"); +} + +// Listen for a new connection request and allocate appropriate data +// structures when one arrives. + +int +ACE_TLI_Request_Queue::enqueue (const char device[], + int restart, int rwflag) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::enqueue"); + ACE_TLI_Request *temp = this->alloc (); + ACE_TLI_Request &req = *this->tail_; + int res; + + do + res = ACE_OS::t_listen (this->handle_, req.callp_); + while (res == ACE_INVALID_HANDLE && restart && t_errno == TSYSERR && errno == EINTR); + + if (res != ACE_INVALID_HANDLE) + { + req.handle_ = open_new_endpoint (this->handle_, device, req.callp_, rwflag); + + if (req.handle_ != ACE_INVALID_HANDLE) + { + temp->next_ = this->tail_->next_; + this->tail_->next_ = temp; + this->tail_ = temp; + this->current_count_++; + return 0; + } + } + + // Something must have gone wrong, so free up allocated space. + this->free (temp); + return ACE_INVALID_HANDLE; +} + +// Locate and remove SEQUENCE_NUMBER from the list of pending +// connections. + +int +ACE_TLI_Request_Queue::remove (int sequence_number) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::remove"); + ACE_TLI_Request *prev = this->tail_; + + // Put the sequence # in the dummy node to simply the search... + prev->callp_->sequence = sequence_number; + + ACE_TLI_Request *temp; + + for (temp = this->tail_->next_; + temp->callp_->sequence != sequence_number; + temp = temp->next_) + prev = temp; + + if (temp == this->tail_) + // Sequence # was not found, since we're back at the dummy node! + return -1; + else + { + prev->next_ = temp->next_; + ACE_OS::t_close (temp->handle_); + this->current_count_--; + this->free (temp); + return 0; + } +} + +ACE_HANDLE +ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap, + int reuse_addr, + int oflag, + struct t_info *info, + int qlen, + const char dev[]) +{ + ACE_TRACE ("ACE_TLI_Acceptor::open"); + int res = 0; + int one = 1; + + this->disp_ = 0; + + if ((this->device_ = ACE_OS::strdup (dev)) == 0) + res = ACE_INVALID_HANDLE; + else if (this->ACE_TLI::open (dev, oflag, info) == ACE_INVALID_HANDLE) + res = ACE_INVALID_HANDLE; + else if (reuse_addr + && this->set_option (SOL_SOCKET, SO_REUSEADDR, + &one, sizeof one) == ACE_INVALID_HANDLE) + res = ACE_INVALID_HANDLE; + else if ((this->disp_ = + (struct t_discon *) ACE_OS::t_alloc (this->get_handle (), T_DIS, T_ALL)) == 0) + res = ACE_INVALID_HANDLE; + else + { + struct t_bind req; + + this->backlog_ = qlen; + req.qlen = qlen; + req.addr.maxlen = remote_sap.get_size (); + + if (&remote_sap == &ACE_Addr::sap_any) + // Note that if addr.len == 0 then ACE_TLI selects the port number. + req.addr.len = 0; + else + { + req.addr.len = remote_sap.get_size (); + req.addr.buf = (char *) remote_sap.get_addr (); + } + + res = ACE_OS::t_bind (this->get_handle (), &req, 0); + if (res != ACE_INVALID_HANDLE) + { + ACE_NEW_RETURN (this->queue_, ACE_TLI_Request_Queue, -1); + + res = this->queue_->open (this->get_handle (), this->backlog_); + } + } + + if (res == ACE_INVALID_HANDLE) + this->close (); + return this->get_handle (); +} + + +ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap, + int reuse_addr, + int oflag, + struct t_info *info, + int back, + const char dev[]) +{ + ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor"); + if (this->open (remote_sap, reuse_addr, oflag, + info, back, dev) == ACE_INVALID_HANDLE) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_TLI_Acceptor::ACE_TLI_Acceptor")); +} + +int +ACE_TLI_Acceptor::close (void) +{ + ACE_TRACE ("ACE_TLI_Acceptor::close"); + if (this->device_ != 0) + { + if (this->queue_ != 0) + { + this->queue_->close (); + delete this->queue_; + } + + ACE_OS::t_free ((char *) this->disp_, T_DIS); + ACE_OS::free (ACE_MALLOC_T (this->device_)); + this->disp_ = 0; + this->device_ = 0; + return this->ACE_TLI::close (); + } + return 0; +} + +// Perform the logic required to handle the arrival of asynchronous +// events while we are trying to accept a new connection request. + +int +ACE_TLI_Acceptor::handle_async_event (int restart, int rwf) +{ + ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event"); + int event; + + switch (event = this->look ()) + { + case T_DISCONNECT: + this->rcvdis (this->disp_); + this->queue_->remove (this->disp_->sequence); + break; + case T_LISTEN: + this->queue_->enqueue (this->device_, restart, rwf); + break; + default: + return -1; + } + return 0; +} + +int +ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap, + ACE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart, + int rwf, + netbuf *udata, + netbuf *opt) +{ + ACE_TRACE ("ACE_TLI_Acceptor::accept"); + ACE_TLI_Request *req = 0; + int res = 0; + + if (timeout != 0 + && ACE::handle_timed_accept (this->get_handle (), + timeout, restart) == -1) + return -1; + else if (this->queue_->is_empty ()) + { + req = this->queue_->alloc (); + + do + res = ACE_OS::t_listen (this->get_handle (), req->callp_); + while (res == ACE_INVALID_HANDLE + && restart + && errno == EINTR); + + if (res != ACE_INVALID_HANDLE) + res = req->handle_ = open_new_endpoint (this->get_handle (), + this->device_, req->callp_, rwf); + } + else + res = this->queue_->dequeue (req); + + if (udata != 0) + ACE_OS::memcpy ((void *) &req->callp_->udata, (void *) udata, sizeof *udata); + if (opt != 0) + ACE_OS::memcpy ((void *) &req->callp_->opt, (void *) opt, sizeof *opt); + + while (res != ACE_INVALID_HANDLE) + if ((res = ACE_OS::t_accept (this->get_handle (), req->handle_, + req->callp_)) != ACE_INVALID_HANDLE) + break; // Got one! + else if (t_errno == TLOOK) + res = this->handle_async_event (restart, rwf); + else if (restart && t_errno == TSYSERR && errno == EINTR) + res = 0; + + if (res == ACE_INVALID_HANDLE) + { + if (errno != EWOULDBLOCK) + { + new_tli_sap.set_handle (ACE_INVALID_HANDLE); + if (req->handle_ != ACE_INVALID_HANDLE) + ACE_OS::t_close (req->handle_); + } + } + else + { + new_tli_sap.set_handle (req->handle_); + + if (remote_addr != 0) + remote_addr->set_addr ((void *) req->callp_->addr.buf, req->callp_->addr.len); + } + + req->handle_ = ACE_INVALID_HANDLE; + this->queue_->free (req); + new_tli_sap.set_rwflag (rwf); + return new_tli_sap.get_handle () == ACE_INVALID_HANDLE ? -1 : 0; +} + +#endif /* ACE_HAS_TLI */ diff --git a/ace/TLI_Acceptor.h b/ace/TLI_Acceptor.h new file mode 100644 index 00000000000..374216c5a18 --- /dev/null +++ b/ace/TLI_Acceptor.h @@ -0,0 +1,109 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// TLI_Acceptor.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TLI_ACCEPTOR_H) +#define ACE_TLI_ACCEPTOR_H + +#include "ace/TLI.h" +#include "ace/Time_Value.h" +#include "ace/TLI_Stream.h" + +#if defined (ACE_HAS_TLI) + +/* Oh what I wouldn't do for namespaces... */ + +// Forward reference... +class ACE_TLI_Request_Queue; + +class ACE_Export ACE_TLI_Acceptor : public ACE_TLI + // = TITLE + // Defines the member functions for ACE_TLI_Acceptor abstraction. + // + // = DESCRIPTION + // This class implements the algorithm described in Steve Rago's + // book on System V UNIX network programming. It basically + // makes TLI look like the C++ SOCK_SAP socket wrappers with + // respect to establishing passive-mode listener endpoints. +{ +friend class ACE_Request_Queue; +public: + // = Initialization and termination methods. + ACE_TLI_Acceptor (void); + // Default constructor. + + ACE_TLI_Acceptor (const ACE_Addr &remote_sap, + int reuse_addr = 0, + int oflag = O_RDWR, + struct t_info *info = 0, + int backlog = 5, + const char device[] = "/dev/tcp"); + // Initiate a passive mode socket. + + ACE_HANDLE open (const ACE_Addr &remote_sap, + int reuse_addr = 0, + int oflag = O_RDWR, + struct t_info *info = 0, + int backlog = 5, + const char device[] = "/dev/tcp"); + // Initiate a passive mode socket. + + int close (void); + // Close down the acceptor and release resources. + + // = Passive connection acceptance method. + + int accept (ACE_TLI_Stream &new_tli_sap, + ACE_Addr *remote_addr = 0, + ACE_Time_Value *timeout = 0, + int restart = 1, + int rwflag = 1, + netbuf *udata = 0, + netbuf *opt = 0); + // Accept a new data transfer connection. A <timeout> of 0 means + // block forever, a <timeout> of {0, 0} means poll. <restart> == 1 + // means "restart if interrupted." + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + const char *device_; + // Network "device" we are using. + + int backlog_; + // Number of connections to queue. + + int rwflag_; + // Are we using "tirdwr" mod? + + int handle_async_event (int restart, int rwflag); + // Handle TLI accept insanity... + + ACE_TLI_Request_Queue *queue_; + // Used for queueing up pending requests. + + struct t_discon *disp_; + // Used for handling disconnects +}; + +#include "ace/TLI_Acceptor.i" + +#endif /* ACE_HAS_TLI */ +#endif /* ACE_TLI_ACCEPTOR_H */ diff --git a/ace/TLI_Acceptor.i b/ace/TLI_Acceptor.i new file mode 100644 index 00000000000..b9dbe6a1a1a --- /dev/null +++ b/ace/TLI_Acceptor.i @@ -0,0 +1,5 @@ +/* -*- C++ -*- */ +// $Id$ + +// TLI_Acceptor.i + diff --git a/ace/TLI_Connector.cpp b/ace/TLI_Connector.cpp new file mode 100644 index 00000000000..2a03693b5d9 --- /dev/null +++ b/ace/TLI_Connector.cpp @@ -0,0 +1,211 @@ +// TLI_Connector.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Handle_Set.h" +#include "ace/TLI_Connector.h" +#include "ace/Time_Value.h" + +#if defined (ACE_HAS_TLI) + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector) + +void +ACE_TLI_Connector::dump (void) const +{ + ACE_TRACE ("ACE_TLI_Connector::dump"); +} + +ACE_TLI_Connector::ACE_TLI_Connector (void) +{ + ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector"); +} + +// Connect the <new_stream> to the <remote_sap>, waiting up to +// <timeout> amount of time if necessary. It's amazing how +// complicated this is to do in TLI... + +int +ACE_TLI_Connector::connect (ACE_TLI_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + const char device[], + struct t_info *info, + int rwf, + netbuf *udata, + netbuf *opt) +{ + ACE_TRACE ("ACE_TLI_Connector::connect"); + int result = 0; + + // Only open a new endpoint if we don't already have a valid handle. + + if (new_stream.get_handle () == ACE_INVALID_HANDLE) + { + if (ACE_TLI::open (device, flags, info) == -1) + return -1; + } + else // Borrow the handle from the NEW_STREAM. + this->set_handle (new_stream.get_handle ()); + + if (&local_sap != &ACE_Addr::sap_any) + { + // Bind the local endpoint to a specific addr. + + struct t_bind *localaddr; + + localaddr = (struct t_bind *) + ::t_alloc (this->get_handle (), T_BIND, T_ADDR); + + if (localaddr == 0) + result = -1; + else + { + int one = 1; + if (reuse_addr && this->set_option (SOL_SOCKET, SO_REUSEADDR, + &one, sizeof one) == -1) + result = -1; + else + { + // localaddr->glen = 0; + localaddr->addr.maxlen = local_sap.get_size (); + localaddr->addr.len = local_sap.get_size (); + localaddr->addr.buf = (char *) local_sap.get_addr (); + + if (ACE_OS::t_bind (this->get_handle (), localaddr, localaddr) == -1) + result = -1; + + ACE_OS::t_free ((char *) localaddr, T_BIND); + } + } + + if (result == -1) + { + this->close (); + return -1; + } + } + // Let TLI select the local endpoint addr. + else if (ACE_OS::t_bind (this->get_handle (), 0, 0) == -1) + return -1; + + struct t_call *callptr = 0; + + callptr = (struct t_call *) + ACE_OS::t_alloc (this->get_handle (), T_CALL, T_ADDR); + + if (callptr == 0) + { + this->close (); + return -1; + } + callptr->addr.maxlen = remote_sap.get_size (); + callptr->addr.len = remote_sap.get_size (); + callptr->addr.buf = (char *) remote_sap.get_addr (); + + if (udata != 0) + ACE_OS::memcpy ((void *) &callptr->udata, (void *) udata, sizeof *udata); + if (opt != 0) + ACE_OS::memcpy ((void *) &callptr->opt, (void *) opt, sizeof *opt); + + // Connect to remote endpoint. + + if (timeout != 0) // Enable non-blocking, if required. + { + if (this->enable (ACE_NONBLOCK) == -1) + result = -1; + + // Do a non-blocking connect. + if (ACE_OS::t_connect (this->get_handle (), callptr, 0) == -1) + { + result = -1; + + // Check to see if we simply haven't connected yet on a + // non-blocking handle or whether there's really an error. + if (t_errno == TNODATA) + { + if (timeout->sec () == 0 && timeout->usec () == 0) + errno = EWOULDBLOCK; + else + result = this->complete (new_stream, 0, timeout); + } + else if (t_errno == TLOOK && this->look () == T_DISCONNECT) + this->rcvdis (); + } + } + // Do a blocking connect to the server. + else if (ACE_OS::t_connect (this->get_handle (), callptr, 0) == -1) + result = -1; + + if (result != -1) + { + // If everything succeeded transfer ownership to <new_stream>. + new_stream.set_handle (this->get_handle ()); + this->set_handle (ACE_INVALID_HANDLE); + new_stream.set_rwflag (rwf); +#if defined (I_PUSH) + if (new_stream.get_rwflag ()) + result = ACE_OS::ioctl (new_stream.get_handle (), I_PUSH, "tirdwr"); +#endif /* I_PUSH */ + } + else if (!(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + { + // If things have gone wrong, close down and return an error. + this->close (); + new_stream.set_handle (ACE_INVALID_HANDLE); + } + + if (ACE_OS::t_free ((char *) callptr, T_CALL) == -1) + return -1; + return result; +} + +// Try to complete a non-blocking connection. + +int +ACE_TLI_Connector::complete (ACE_TLI_Stream &new_stream, + ACE_Addr *remote_sap, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_TLI_Connector::complete"); + ACE_HANDLE h = ACE::handle_timed_complete (this->get_handle (), tv); + + if (h == ACE_INVALID_HANDLE) + { + this->close (); + return -1; + } + else // We've successfully connected! + { + if (remote_sap != 0) + { +#if defined (ACE_HAS_SVR4_TLI) + struct netbuf name; + + name.maxlen = remote_sap->get_size (); + name.buf = (char *) remote_sap->get_addr (); + + if (ACE_OS::ioctl (this->get_handle (), TI_GETPEERNAME, &name) == -1) +#else /* SunOS4 sucks... */ + if (0) +#endif /* ACE_HAS_SVR4_TLI */ + { + this->close (); + return -1; + } + } + new_stream.set_handle (this->get_handle ()); + + // Start out with non-blocking disabled on the <new_stream>. + new_stream.disable (ACE_NONBLOCK); + + this->set_handle (ACE_INVALID_HANDLE); + return 0; + } +} + +#endif /* ACE_HAS_TLI */ diff --git a/ace/TLI_Connector.h b/ace/TLI_Connector.h new file mode 100644 index 00000000000..4120cccd58d --- /dev/null +++ b/ace/TLI_Connector.h @@ -0,0 +1,104 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// TLI_Connector.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TLI_CONNECTOR_H) +#define ACE_TLI_CONNECTOR_H + +#include "ace/TLI_Stream.h" + +#if defined (ACE_HAS_TLI) + +class ACE_Export ACE_TLI_Connector : public ACE_TLI + // = TITLE + // Defines an active connection factory for the ACE_TLI C++ wrappers. +{ +public: + // = Initialization methods. + ACE_TLI_Connector (void); + // Default constructor. + + ACE_TLI_Connector (ACE_TLI_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0, + const char device[] = "/dev/tcp", + struct t_info *info = 0, + int rw_flag = 1, + struct netbuf *udata = 0, + struct netbuf *opt = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + int connect (ACE_TLI_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0, + const char device[] = "/dev/tcp", + struct t_info *info = 0, + int rw_flag = 1, + struct netbuf *udata = 0, + struct netbuf *opt = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + int complete (ACE_TLI_Stream &new_stream, + ACE_Addr *remote_sap, + ACE_Time_Value *tv); + // Try to complete a non-blocking connection. + // If connection completion is successful then <new_stream> contains + // the connected ACE_SOCK_Stream. If <remote_sap> is non-NULL then it + // will contain the address of the connected peer. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/TLI_Connector.i" + +#endif /* ACE_HAS_TLI */ +#endif /* ACE_TLI_CONNECTOR_H */ diff --git a/ace/TLI_Connector.i b/ace/TLI_Connector.i new file mode 100644 index 00000000000..8cfb13e193e --- /dev/null +++ b/ace/TLI_Connector.i @@ -0,0 +1,29 @@ +/* -*- C++ -*- */ +// $Id$ + +// TLI_Connector.i + +#include "ace/Log_Msg.h" + +inline +ACE_TLI_Connector::ACE_TLI_Connector (ACE_TLI_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + const char device[], + struct t_info *info, + int rwf, + netbuf *udata, + netbuf *opt) +{ + ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector"); + if (this->connect (new_stream, remote_sap, timeout, local_sap, reuse_addr, + flags, perms, device, + info, rwf, + udata, opt) == ACE_INVALID_HANDLE + && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_TLI_Stream::ACE_TLI_Stream")); +} diff --git a/ace/TLI_Stream.cpp b/ace/TLI_Stream.cpp new file mode 100644 index 00000000000..babca46d529 --- /dev/null +++ b/ace/TLI_Stream.cpp @@ -0,0 +1,99 @@ +// TLI_Stream.cpp +// $Id$ + +/* Defines the member functions for the base class of the ACE_TLI_Stream + abstraction. */ + +#define ACE_BUILD_DLL +#include "ace/TLI_Stream.h" +#include "ace/Log_Msg.h" + +#if defined (ACE_HAS_TLI) + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Stream) + +void +ACE_TLI_Stream::dump (void) const +{ + ACE_TRACE ("ACE_TLI_Stream::dump"); +} + +ACE_TLI_Stream::ACE_TLI_Stream (void) +{ + ACE_TRACE ("ACE_TLI_Stream::ACE_TLI_Stream"); +} + +int +ACE_TLI_Stream::get_remote_addr (ACE_Addr &sa) const +{ + ACE_TRACE ("ACE_TLI_Stream::get_remote_addr"); + struct netbuf name; + + name.maxlen = sa.get_size (); + name.buf = (char *) sa.get_addr (); + +#if defined (ACE_HAS_SVR4_TLI) + if (ACE_OS::ioctl (this->get_handle (), TI_GETPEERNAME, &name) == -1) +/* if (ACE_OS::t_getname (this->get_handle (), &name, REMOTENAME) == -1) */ + +#else /* SunOS4 sucks... */ + if (0) +#endif /* ACE_HAS_SVR4_TLI */ + return -1; + else + return 0; +} + +/* Send a release and then await the release from the other side */ + +int +ACE_TLI_Stream::active_close (void) +{ + ACE_TRACE ("ACE_TLI_Stream::active_close"); + char buf; + + if (this->sndrel () == ACE_INVALID_HANDLE) + return ACE_INVALID_HANDLE; + if (this->recv (&buf, sizeof buf) == ACE_INVALID_HANDLE) + { + if (t_errno == TLOOK && this->look () == T_ORDREL) + { + if (this->rcvrel () == ACE_INVALID_HANDLE) + return ACE_INVALID_HANDLE; + } + else + return ACE_INVALID_HANDLE; + } + return this->close (); +} + +/* Acknowledge the release from the other side and then send the release to + the other side. */ + +int +ACE_TLI_Stream::passive_close (void) +{ + ACE_TRACE ("ACE_TLI_Stream::passive_close"); + if (this->rcvrel () == ACE_INVALID_HANDLE) + return ACE_INVALID_HANDLE; + if (this->sndrel () == ACE_INVALID_HANDLE) + return ACE_INVALID_HANDLE; + return this->close (); +} + + +int +ACE_TLI_Stream::close (void) +{ + ACE_TRACE ("ACE_TLI_Stream::close"); + int fd = this->get_handle (); + + this->set_handle (ACE_INVALID_HANDLE); + + if (this->rwflag_) + return ACE_OS::close (fd); + else + return ACE_OS::t_close (fd); +} + +#endif /* ACE_HAS_TLI */ diff --git a/ace/TLI_Stream.h b/ace/TLI_Stream.h new file mode 100644 index 00000000000..73a7391a3fd --- /dev/null +++ b/ace/TLI_Stream.h @@ -0,0 +1,93 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// TLI_Stream.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TLI_STREAM_H) +#define ACE_TLI_STREAM_H + +#include "ace/TLI.h" +#include "ace/INET_Addr.h" + +#if defined (ACE_HAS_TLI) + +class ACE_Export ACE_TLI_Stream : public ACE_TLI + // = TITLE + // Defines the member functions for ACE_TLI_Stream abstraction. +{ +friend class ACE_TLI_Acceptor; +friend class ACE_TLI_Connector; +public: + // = Initialization and termination methods. + ACE_TLI_Stream (void); + // Default constructor. + + // = TLI-specific shutdown operations. + int close (void); + // Close down and release resources. + + int active_close (void); + // Send a release and then await the release from the other side. + + int passive_close (void); + // Acknowledge the release from the other side and then send the + // release to the other side. + + int get_remote_addr (ACE_Addr &) const; + // Return address of remotely connected peer. + + // = timod bindings + ssize_t send (const void *buf, size_t n, int flags) const; + // Send an n byte buffer to the connected socket (uses t_snd(3)). + ssize_t recv (void *buf, size_t n, int *flags) const; + // Recv an n byte buffer from the connected socket (uses t_rcv(3)). + + ssize_t send_n (const void *buf, size_t n, int flags) const; + // Send exactly n bytes to the connected socket (uses t_snd(3)). + ssize_t recv_n (void *buf, size_t n, int *flags) const; + // Recv exactly n bytes from the connected socket (uses t_rcv(3)). + + // = tirdwr bindings + ssize_t send (const void *buf, size_t n) const; + // Send an n byte buffer to the connected socket (uses write(2)). + + ssize_t recv (void *buf, size_t n) const; + // Recv an n byte buffer from the connected socket (uses read(2)). + + ssize_t send_n (const void *buf, size_t n) const; + // Send n bytes, keep trying until n are sent (uses write(2)). + + ssize_t recv_n (void *buf, size_t n) const; + // Recv n bytes, keep trying until n are received (uses read (2)). + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int rwflag_; + // Indicates whether the tirdwr module should be pushed + + // = Get/set rwflag + int get_rwflag (void); + void set_rwflag (int); +}; + +#include "ace/TLI_Stream.i" + +#endif /* ACE_HAS_TLI */ +#endif /* ACE_TLI_STREAM_H */ diff --git a/ace/TLI_Stream.i b/ace/TLI_Stream.i new file mode 100644 index 00000000000..646c25d8008 --- /dev/null +++ b/ace/TLI_Stream.i @@ -0,0 +1,105 @@ +/* -*- C++ -*- */ +// $Id$ + +// TLI_Stream.i + +#include "ace/TLI_Stream.h" + +inline ssize_t +ACE_TLI_Stream::send (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_TLI_Stream::send"); + return ACE_OS::write (this->get_handle (), (const char *) buf, n); +} + +inline ssize_t +ACE_TLI_Stream::send (const void *buf, size_t n, int flags) const +{ + ACE_TRACE ("ACE_TLI_Stream::send"); + return ACE_OS::t_snd (this->get_handle (), (char *) buf, n, flags); +} + +inline ssize_t +ACE_TLI_Stream::recv (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_TLI_Stream::recv"); + return ACE_OS::read (this->get_handle (), (char *) buf, n); +} + +inline ssize_t +ACE_TLI_Stream::recv (void *buf, size_t n, int *flags) const +{ + ACE_TRACE ("ACE_TLI_Stream::recv"); + int f = 0; + + if (flags == 0) + flags = &f; + return ACE_OS::t_rcv (this->get_handle (), (char *) buf, n, flags); +} + +inline ssize_t +ACE_TLI_Stream::send_n (const void *buf, size_t n) const +{ + ACE_TRACE ("ACE_TLI_Stream::send_n"); + return ACE::send_n (this->get_handle (), buf, n); +} + +inline ssize_t +ACE_TLI_Stream::send_n (const void *buf, size_t n, int flags) const +{ + ACE_TRACE ("ACE_TLI_Stream::send_n"); + int b_sent; + int b_written; + + for (b_sent = 0; b_sent < n; b_sent += b_written) + if ((b_written = ACE_OS::t_snd (this->get_handle (), + (char *) buf + b_sent, + n - b_sent, flags)) == -1) + return -1; + + return b_sent; +} + +inline ssize_t +ACE_TLI_Stream::recv_n (void *buf, size_t n) const +{ + ACE_TRACE ("ACE_TLI_Stream::recv_n"); + return ACE::recv_n (this->get_handle (), buf, n); +} + +inline ssize_t +ACE_TLI_Stream::recv_n (void *buf, size_t n, int *flags) const +{ + ACE_TRACE ("ACE_TLI_Stream::recv_n"); + int b_read = 0; + int b_recv = 0; + int f = 0; + + if (flags == 0) + flags = &f; + + for (b_read = 0; b_read < n; b_read += b_recv) + if ((b_recv = ACE_OS::t_rcv (this->get_handle (), + (char *) buf + b_read, + n - b_read, flags)) == -1) + return -1; + else if (b_recv == 0) + break; + + return b_read; +} + +inline void +ACE_TLI_Stream::set_rwflag (int value) +{ + ACE_TRACE ("ACE_TLI_Stream::set_rwflag"); + this->rwflag_ = value; +} + +inline int +ACE_TLI_Stream::get_rwflag (void) +{ + ACE_TRACE ("ACE_TLI_Stream::get_rwflag"); + return this->rwflag_; +} + diff --git a/ace/TTY_IO.cpp b/ace/TTY_IO.cpp new file mode 100644 index 00000000000..96d63e80618 --- /dev/null +++ b/ace/TTY_IO.cpp @@ -0,0 +1,211 @@ +// TTY_IO.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/TTY_IO.h" + +// Interface for reading/writing serial device parameters + +int +ACE_TTY_IO::control (Control_Mode cmd, + Serial_Params *arg) const +{ +#if defined (ACE_HAS_TERM_IOCTLS) + struct termios devpar; + u_long c_iflag; + u_long c_oflag; + u_long c_cflag; + u_long c_lflag; + u_long c_line; + u_char ivmin_cc4; + u_char ivtime_cc5; + + c_iflag=0; + c_oflag=0; + c_cflag=0; + c_lflag=0; + c_line=0; + + // Get default device parameters. + + if (this->ACE_IO_SAP::control (TCGETS, (void *) &devpar) == -1) + return -1; + + switch (cmd) + { + case SETPARAMS: + switch (arg->baudrate) + { + case 600: + c_cflag |= B600; + break; + case 1200: + c_cflag |= B1200; + break; + case 2400: + c_cflag |= B2400; + break; + case 4800: + c_cflag |= B4800; + break; + case 9600: + c_cflag |= B9600; + break; + case 19200: + c_cflag |= B19200; + break; + + case 38400: + c_cflag |= B38400; + break; + default: + return -1; + } + switch (arg->databits) + { + case 5: + c_cflag |= CS5; + break; + case 6: + c_cflag |= CS6; + break; + case 7: + c_cflag |= CS7; + break; + case 8: + c_cflag |= CS8; + break; + default: + return -1; + } + switch (arg->stopbits) + { + case 1: + break; + case 2: + c_cflag |= CSTOPB; + break; + default: + return -1; + } + if (arg->parityenb) + { + c_cflag |= PARENB; + if (strcmp((char *) arg->paritymode,"ODD")==0 || + strcmp((char *) arg->paritymode,"odd")==0) + c_cflag |= PARODD; + } + if (arg->ctsenb) /* enable CTS/RTS protocoll */ + c_cflag |= CRTSCTS; + if (arg->rcvenb) /* enable receiver */ + c_cflag |= CREAD; + + c_oflag=0; + c_iflag=IGNPAR|INPCK|ISTRIP; + c_lflag=0; + + ivmin_cc4 =(u_char)0; + ivtime_cc5=(u_char)(arg->readtimeoutmsec/100); + devpar.c_iflag = c_iflag; + devpar.c_oflag = c_oflag; + devpar.c_cflag = c_cflag; + devpar.c_lflag = c_lflag; + devpar.c_cc[4] = ivmin_cc4; + devpar.c_cc[5] = ivtime_cc5; + + return this->ACE_IO_SAP::control (TCSETS, (void *) &devpar); + + case GETPARAMS: + return -1; // Not yet implemented. + + default: + return -1; // Wrong cmd. + } +#elif defined (ACE_WIN32) + switch (cmd) + { + case SETPARAMS: + DCB dcb ; + dcb.DCBlength = sizeof dcb ; + ::GetCommState (this->get_handle (), &dcb); + + switch (arg->baudrate) + { + case 600: dcb.BaudRate = CBR_600; break; + case 1200: dcb.BaudRate = CBR_1200; break; + case 2400: dcb.BaudRate = CBR_2400; break; + case 4800: dcb.BaudRate = CBR_4800; break; + case 9600: dcb.BaudRate = CBR_9600; break; + case 19200: dcb.BaudRate = CBR_19200; break; + case 38400: dcb.BaudRate = CBR_38400; break; + default: return -1; + } + + switch (arg->databits) + { + case 4: + case 5: + case 6: + case 7: + case 8: + dcb.ByteSize = arg->databits; + break; + default: + return -1; + } + + switch (arg->stopbits) + { + case 1: dcb.StopBits = ONESTOPBIT ; break ; + case 2: dcb.StopBits = TWOSTOPBITS; break ; + break; + default: + return -1; + } + + if (arg->parityenb) + { + dcb.fParity = TRUE ; + if (ACE_OS::strcmp ((char *) arg->paritymode, "ODD") == 0 + || ACE_OS::strcmp ((char *) arg->paritymode, "odd") == 0) + dcb.Parity = ODDPARITY ; + else if (ACE_OS::strcmp ((char *) arg->paritymode, "EVEN") == 0 + || ACE_OS::strcmp ((char *) arg->paritymode, "even") == 0) + dcb.Parity = EVENPARITY ; + } + else + { + dcb.fParity = FALSE ; + dcb.Parity = NOPARITY ; + } + + if (arg->ctsenb) // enable CTS/RTS protocol. + { + dcb.fOutxCtsFlow = TRUE ; + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE ; + } + else + { + dcb.fOutxCtsFlow = FALSE ; + dcb.fRtsControl = RTS_CONTROL_DISABLE ; + } + dcb.fBinary = TRUE ; + return ::SetCommState (this->get_handle (), &dcb); + + case GETPARAMS: + ACE_NOTSUP_RETURN (-1); // Not yet implemented. + default: + return -1; // Wrong cmd. + + } // arg switch +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TERM_IOCTLS */ +} + +ACE_TTY_IO::operator ACE_DEV_IO &() +{ + return (ACE_DEV_IO &) *this; +} + diff --git a/ace/TTY_IO.h b/ace/TTY_IO.h new file mode 100644 index 00000000000..0e348f244cb --- /dev/null +++ b/ace/TTY_IO.h @@ -0,0 +1,67 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// TTY_IO.h +// +// = DESCRIPTION +// +// = AUTHOR +// Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_TTY_H) +#define ACE_TTY_H + +#include "ace/Log_Msg.h" +#include "ace/OS.h" +#include "ace/DEV_Addr.h" +#include "ace/DEV_Connector.h" +#include "ace/DEV_IO.h" + +class ACE_TTY_IO : public ACE_DEV_IO + // = TITLE + // Class definitions for TTY-specific features. + // + // = DESCRIPTION + // This class represents an example interface for a specific + // device (a serial line) It extends the capability of the + // underlying DEV_IO class by adding a control method that takes + // a special structure (Serial_Params) as argument to allow a + // comfortable user interface (away from that annoying termios + // structure, which is very specific to UNIX). +{ +public: + enum Control_Mode + { + SETPARAMS, // Set control parameters. + GETPARAMS // Get control parameters. + }; + + struct Serial_Params + { + int baudrate; + int parityenb; + char *paritymode; + int databits; + int stopbits; + int readtimeoutmsec; + int ctsenb; + int rcvenb; + }; + + int control (Control_Mode cmd, Serial_Params * arg) const; + // Interface for reading/writing serial device parameters. + + operator ACE_DEV_IO &(); + // This is necessary to pass ACE_TTY_IO as parameter to DEV_Connector. +}; + +#endif /* ACE_TTY_H */ diff --git a/ace/Task.cpp b/ace/Task.cpp new file mode 100644 index 00000000000..e726a234af3 --- /dev/null +++ b/ace/Task.cpp @@ -0,0 +1,305 @@ +// Task.cpp +// $Id$ + +#if !defined (ACE_TASK_C) +#define ACE_TASK_C + +#define ACE_BUILD_DLL +#include "ace/Task.h" +#include "ace/Module.h" +#include "ace/Service_Config.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Task.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) +// Lock the creation of the Singleton. +template <ACE_SYNCH_1> +ACE_Thread_Mutex ACE_Task_Exit<ACE_SYNCH_2>::ace_task_lock_; +#endif /* defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ + +template<ACE_SYNCH_1> ACE_Task_Exit<ACE_SYNCH_2> * +ACE_Task_Exit<ACE_SYNCH_2>::instance (void) +{ + ACE_TRACE ("ACE_Task_Exit<ACE_SYNCH_2>::instance"); + +#if defined (ACE_MT_SAFE) && defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + // Lock the creation of the Singleton. This should be inside of + // ACE_Svc_Handler, but GNU G++ is too lame to handle this... + static ACE_Thread_Mutex ace_task_lock_; +#endif /* defined (ACE_MT_SAFE) && defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ + + // Determines if we were dynamically allocated. + static ACE_TSS_TYPE (ACE_Task_Exit<ACE_SYNCH_2>) *instance_; + + // Implement the Double Check pattern. + + if (instance_ == 0) + { + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ace_task_lock_, 0)); + + if (instance_ == 0) + ACE_NEW_RETURN (instance_, ACE_TSS_TYPE (ACE_Task_Exit<ACE_SYNCH_2>), 0); + } + + return ACE_TSS_GET (instance_, ACE_Task_Exit<ACE_SYNCH_2>); + +} + +// Grab hold of the Task * so that we can close() it in the +// destructor. + +template<ACE_SYNCH_1> +ACE_Task_Exit<ACE_SYNCH_2>::ACE_Task_Exit (void) + : t_ (0), + status_ ((void *) -1) +{ + ACE_TRACE ("ACE_Task_Exit<ACE_SYNCH_2>::ACE_Task_Exit"); +} + +// Set the this pointer... + +template<ACE_SYNCH_1> void +ACE_Task_Exit<ACE_SYNCH_2>::set_this (ACE_Task<ACE_SYNCH_2> *t) +{ + ACE_TRACE ("ACE_Task_Exit<ACE_SYNCH_2>::set_this"); + this->t_ = t; + + if (t != 0) + this->tc_.insert (t->thr_mgr ()); +} + +// Set the thread exit status value. + +template<ACE_SYNCH_1> void * +ACE_Task_Exit<ACE_SYNCH_2>::status (void *s) +{ + ACE_TRACE ("ACE_Task_Exit<ACE_SYNCH_2>::status"); + return this->status_ = s; +} + +template<ACE_SYNCH_1> void * +ACE_Task_Exit<ACE_SYNCH_2>::status (void) +{ + ACE_TRACE ("ACE_Task_Exit<ACE_SYNCH_2>::status"); + return this->status_; +} + +// When this object is destroyed the Task is automatically closed +// down! + +template<ACE_SYNCH_1> +ACE_Task_Exit<ACE_SYNCH_2>::~ACE_Task_Exit (void) +{ + ACE_TRACE ("ACE_Task_Exit<ACE_SYNCH_2>::~ACE_Task_Exit"); + + if (this->t_ != 0) + { + // The thread count must be decremented first in case the + // close() hook does something crazy like "delete this". + this->t_->thr_count_dec (); + this->t_->close (u_long (this->status_)); + } +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Task) + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::dump (void) const +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "\nthr_mgr_ = %x", this->thr_mgr_)); + this->msg_queue_->dump (); + ACE_DEBUG ((LM_DEBUG, "delete_msg_queue_ = %d\n", this->delete_msg_queue_)); + ACE_DEBUG ((LM_DEBUG, "\nflags = %x", this->flags_)); + ACE_DEBUG ((LM_DEBUG, "\nmod_ = %x", this->mod_)); + ACE_DEBUG ((LM_DEBUG, "\nnext_ = %x", this->next_)); + ACE_DEBUG ((LM_DEBUG, "\ngrp_id_ = %d", this->grp_id_)); + ACE_DEBUG ((LM_DEBUG, "\nthr_count_ = %d", this->thr_count_)); +#if defined (ACE_MT_SAFE) + this->lock_.dump (); +#endif /* ACE_MT_SAFE */ + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// If the user doesn't supply a ACE_Message_Queue pointer then we'll +// allocate one dynamically. Otherwise, we'll use the one they give. + +template<ACE_SYNCH_1> +ACE_Task<ACE_SYNCH_2>::ACE_Task (ACE_Thread_Manager *thr_man, + ACE_Message_Queue<ACE_SYNCH_2> *mq) + : delete_msg_queue_ (0), + thr_mgr_ (thr_man), + mod_ (0), + flags_ (0), + grp_id_ (0), + thr_count_ (0), + msg_queue_ (0), + next_ (0) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::ACE_Task"); + + if (mq == 0) + { + ACE_NEW (mq, ACE_Message_Queue<ACE_SYNCH_2>); + this->delete_msg_queue_ = 1; + } + + this->msg_queue_ = mq; +} + +template<ACE_SYNCH_1> +ACE_Task<ACE_SYNCH_2>::~ACE_Task (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::~ACE_Task"); + if (this->delete_msg_queue_) + delete this->msg_queue_; + + // These assignments aren't strickly necessary but they help guard + // against odd race conditions... + this->delete_msg_queue_ = 0; + this->msg_queue_ = 0; + this->thr_mgr_ = 0; + this->mod_ = 0; +} + +// Note that this routine often does not return since the thread that +// is executing it will do an ACE_Thread::exit() first! + +template<ACE_SYNCH_1> void * +ACE_Task<ACE_SYNCH_2>::svc_run (ACE_Task<ACE_SYNCH_2> *t) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::svc_run"); + + // Obtain our thread-specific exit hook and make sure that it knows + // how to clean us up! + ACE_Task_Exit<ACE_SYNCH_2> *exit_hook = + ACE_Task_Exit<ACE_SYNCH_2>::instance (); + + exit_hook->set_this (t); + + // Call the Task's svc() method. + void *status = (void *) t->svc (); + + return exit_hook->status (status); + /* NOTREACHED */ +} + +template<ACE_SYNCH_1> ACE_Task<ACE_SYNCH_2> * +ACE_Task<ACE_SYNCH_2>::sibling (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::sibling"); + if (this->mod_ == 0) + return 0; + else + return this->mod_->sibling (this); +} + +template<ACE_SYNCH_1> const char * +ACE_Task<ACE_SYNCH_2>::name (void) const +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::name"); + if (this->mod_ == 0) + return 0; + else + return this->mod_->name (); +} + +template<ACE_SYNCH_1> ACE_Module<ACE_SYNCH_2> * +ACE_Task<ACE_SYNCH_2>::module (void) const +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::module"); + return this->mod_; +} + +// Get the current group id. +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::grp_id (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::grp_id"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + return this->grp_id_; +} + +// Set the current group id. +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::grp_id (int id) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::grp_id"); + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_)); + this->grp_id_ = id; +} + +// Suspend a task. +template<ACE_SYNCH_1> int +ACE_Task<ACE_SYNCH_2>::suspend (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::suspend"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + if (this->thr_count_ > 0) + return this->thr_mgr_->suspend_grp (this->grp_id_); + else + return 0; +} + +// Resume a suspended task. +template<ACE_SYNCH_1> int +ACE_Task<ACE_SYNCH_2>::resume (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::resume"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + if (this->thr_count_ > 0) + return this->thr_mgr_->resume_grp (this->grp_id_); + else + return 0; +} + +template<ACE_SYNCH_1> int +ACE_Task<ACE_SYNCH_2>::activate (long flags, + int n_threads, + int force_active, + u_int priority, + int grp_id) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::activate"); + +#if defined (ACE_MT_SAFE) + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + if (this->thr_count_ > 0 && force_active == 0) + return 1; // Already active. + else + this->thr_count_ = n_threads; + + // Use the ACE_Thread_Manager singleton if we're running as an + // active object and the caller didn't supply us with a + // Thread_Manager. + if (this->thr_mgr_ == 0) + this->thr_mgr_ = ACE_Service_Config::thr_mgr (); + + this->grp_id_ = this->thr_mgr_->spawn_n (n_threads, + ACE_THR_FUNC (&ACE_Task<ACE_SYNCH_2>::svc_run), + (void *) this, + flags, + priority, + grp_id); + if (this->grp_id_ == -1) + return -1; + else + return 0; +#else + { + // Keep the compiler from complaining. + n_threads = n_threads; + force_active = force_active; + flags = flags; + errno = EINVAL; + return -1; + } +#endif /* ACE_MT_SAFE */ +} + +#endif /* ACE_TASK_C */ diff --git a/ace/Task.h b/ace/Task.h new file mode 100644 index 00000000000..5290c67b354 --- /dev/null +++ b/ace/Task.h @@ -0,0 +1,299 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Task.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TASK_H) +#define ACE_TASK_H + +#include "ace/Service_Object.h" +#include "ace/Message_Queue.h" +#include "ace/Thread_Manager.h" +#include "ace/Synch_T.h" + +// Forward decls... +template <ACE_SYNCH_1> class ACE_Module; +template <ACE_SYNCH_1> class ACE_Task_Exit; + +class ACE_Task_Flags + // = TITLE + // These flags are used within the ACE_Task. + // + // = DESCRIPTION + // These flags should be hidden within ACE_Task. Unfortunately, the + // HP/UX C++ compiler can't grok this... Fortunately, there's no + // code defined here, so we don't have to worry about multiple + // definitions. +{ +public: + enum + { + ACE_READER = 01, // Identifies a Task as being the "reader" in a Module. + ACE_FLUSHDATA = 02, // Just flush data messages in the queue. + ACE_FLUSHALL = 04, // Flush all messages in the Queue. + ACE_FLUSHR = 010, // flush read queue + ACE_FLUSHW = 020, // flush write queue + ACE_FLUSHRW = 030 // flush both queues + }; +}; + +template <ACE_SYNCH_1> +class ACE_Task : public ACE_Service_Object + // = TITLE + // Primary interface for application message processing, as well + // as input and output message queueing. + // + // = DESCRIPTION + // This class serves as the basis for passive and active objects + // in ACE. +{ +friend class ACE_Module<ACE_SYNCH_2>; +friend class ACE_Module_Type; +friend class ACE_Task_Exit<ACE_SYNCH_2>; +public: + // = Initialization/termination methods. + ACE_Task (ACE_Thread_Manager *thr_mgr = 0, + ACE_Message_Queue<ACE_SYNCH_2> *mq = 0); + // Initialize a Task, supplying a thread manager and a message + // queue. If the user doesn't supply a ACE_Message_Queue pointer + // then we'll allocate one dynamically. Otherwise, we'll use the + // one they give. + + // = Initialization and termination hooks (note that these *must* be + // defined by subclasses). + virtual int open (void *args = 0) = 0; + // Hook called to open a Task. <args> can be used to pass arbitrary + // information into <open>. + + virtual int close (u_long flags = 0) = 0; + // Hook called to close a Task. + + virtual ~ACE_Task (void); + // Destructor. + + // = Immediate and deferred processing methods, respectively. + virtual int put (ACE_Message_Block *, ACE_Time_Value *tv = 0) = 0; + // Transfer msg into the queue to handle immediate processing. + + virtual int svc (void); + // Run by a daemon thread to handle deferred processing. + + // = Active object activation method. + virtual int activate (long flags = THR_NEW_LWP, + int n_threads = 1, + int force_active = 0, + u_int priority = 0, + int grp_id = -1); + // Turn the task into an active object, i.e., having <n_threads> of + // control, all running at the <priority> level with the same + // <grp_id>, all of which invoke <Task::svc>. Returns -1 if failure + // occurs, returns 1 if Task is already an active object and + // <force_active> is false (doesn't *not* create a new thread in + // this case), and returns 0 if Task was not already an active + // object and a thread is created successfully or thread is an + // active object and <force_active> is true. + + // = Suspend/resume a Task + virtual int suspend (void); + // Suspend a task. + virtual int resume (void); + // Resume a suspended task. + + int grp_id (void); + // Get the current group id. + + void grp_id (int); + // Set the current group id. + + ACE_Thread_Manager *thr_mgr (void); + // Gets the thread manager associated with this Task. + + void thr_mgr (ACE_Thread_Manager *); + // Set the thread manager associated with this Task. + + ACE_Message_Queue<ACE_SYNCH_2> *msg_queue (void); + // Gets the message queue associated with this task. + + void msg_queue (ACE_Message_Queue<ACE_SYNCH_2> *); + // Sets the message queue associated with this task. + + size_t thr_count (void); + // Returns the number of threads currently running within a task. + // If we're a passive object this value is 0, else it's > 0. + +public: /* Should be protected: */ + static void *svc_run (ACE_Task<ACE_SYNCH_2> *); + // Routine that runs the service routine as a daemon thread. + + // = Message queue manipulation methods. + + int can_put (ACE_Message_Block *); + // Tests whether we can enqueue a message without blocking. + + int putq (ACE_Message_Block *, ACE_Time_Value *tv = 0); + // Insert message into the message list. + + int getq (ACE_Message_Block *&mb, ACE_Time_Value *tv = 0); + // Extract the first message from the list (blocking). + + int ungetq (ACE_Message_Block *, ACE_Time_Value *tv = 0); + // Return a message to the queue. + + int put_next (ACE_Message_Block *msg, ACE_Time_Value *tv = 0); + // Transfer message to the adjacent ACE_Task in a ACE_Stream. + + int reply (ACE_Message_Block *, ACE_Time_Value *tv = 0); + // Turn the message back around. + + // = ACE_Task utility routines to identify names et al. + const char *name (void) const; + // Return the name of the enclosing Module if there's one associated + // with the Task, else returns 0. + + ACE_Task<ACE_SYNCH_2> *sibling (void); + // Return the Task's sibling if there's one associated with the + // Task's Module, else returns 0. + + ACE_Module<ACE_SYNCH_2> *module (void) const; + // Return the Task's Module if there is one, else returns 0. + + int is_reader (void); + // True if queue is a reader, else false. + + int is_writer (void); + // True if queue is a writer, else false. + + // = Pointers to next ACE_Queue (if ACE is part of an ACE_Stream). + ACE_Task<ACE_SYNCH_2> *next (void); + // Get next Task pointer. + void next (ACE_Task<ACE_SYNCH_2> *); + // Set next Task pointer. + + int flush (u_long flag = ACE_Task_Flags::ACE_FLUSHALL); /* Flush the queue */ + // Special routines corresponding to certain message types. + + void water_marks (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds, size_t); + // Manipulate watermarks. + + void thr_count_dec (void); + // Atomically decrement the thread count by 1. This should only be + // called by the <ACE_Task_Exit> class destructor. + + // = Internal data (should be private...). +// private: + + size_t thr_count_; + // Count of the number of threads running within the task. If this + // value is > 0 then we're an active object and the value of + // <thr_count_> is the number of active threads at this instant. If + // the value == 0, then we're a passive object. + + ACE_Thread_Manager *thr_mgr_; + // Multi-threading manager. + + ACE_Message_Queue<ACE_SYNCH_2> *msg_queue_; + // List of messages on the ACE_Task.. + + int delete_msg_queue_; + // 1 if should delete Message_Queue, 0 otherwise. + + u_long flags_; + // ACE_Task flags. + + ACE_Module<ACE_SYNCH_2> *mod_; + // Back-pointer to the enclosing module. + + ACE_Task<ACE_SYNCH_2> *next_; + // Pointer to adjacent ACE_Task. + + int grp_id_; + // This maintains the group id of the + +#if defined (ACE_MT_SAFE) + ACE_Thread_Mutex lock_; + // Protect the state of a Task during concurrent operations, but + // only if we're configured as MT safe... +#endif /* ACE_MT_SAFE */ + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +template<ACE_SYNCH_1> +class ACE_Task_Exit + // = TITLE + // Keep exit information for a Task in thread specific storage so + // that the Task::close() method will get called no matter how + // the thread exits (e.g., via Thread::exit() or by "falling off + // the end of Task::svc_run"). + // + // = DESCRIPTION + // This clever little helper class is stored in thread-specific + // storage using the ACE_TSS wrapper. When a thread + // exits the ACE_TSS::cleanup() function calls + // "delete" on this object, thereby closing it down gracefully. +{ +public: + ACE_Task_Exit (void); + // Capture the Task object that will be cleaned up automatically. + + void set_this (ACE_Task<ACE_SYNCH_2> *t); + // Set the this pointer... + + void *status (void *s); + // Set the exit status. + + void *status (void); + // Get the exit status. + + ~ACE_Task_Exit (void); + // Destructor calls the <close> method of the captured Task on exit. + + static ACE_Task_Exit<ACE_SYNCH_2> *instance (void); + // Singleton access point. + +private: + ACE_Task<ACE_SYNCH_2> *t_; + // Pointer to the captured Task. + + void *status_; + // Exit status... + + ACE_Thread_Control tc_; + // This is used to make sure that an ACE_Task registers and + // deregisters with the ACE_Thread_Manager correctly. + +#if defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + static ACE_Thread_Mutex ace_task_lock_; + // Lock the creation of the Singleton. +#endif /* defined (ACE_MT_SAFE) && !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ +}; + +#if defined (__ACE_INLINE__) +#include "ace/Task.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Task.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Task.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_TASK_H */ diff --git a/ace/Task.i b/ace/Task.i new file mode 100644 index 00000000000..22d2c6cfb09 --- /dev/null +++ b/ace/Task.i @@ -0,0 +1,160 @@ +/* -*- C++ -*- */ +// $Id$ + +// Task.i + +#include "ace/Log_Msg.h" + +// Return the count of the current number of threads. +template <ACE_SYNCH_1> ACE_INLINE size_t +ACE_Task<ACE_SYNCH_2>::thr_count (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::thr_count"); + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); + + return this->thr_count_; +} + +// Decrement the count of the active threads by 1. + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::thr_count_dec (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::thr_count_dec"); + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_)); + + this->thr_count_--; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::water_marks (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd, + size_t size) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::water_marks"); + if (cmd == ACE_IO_Cntl_Msg::SET_LWM) + this->msg_queue_->low_water_mark (size); + else /* cmd == ACE_IO_Cntl_Msg::SET_HWM */ + this->msg_queue_->high_water_mark (size); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::getq (ACE_Message_Block *&mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::getq"); + return this->msg_queue_->dequeue_head (mb, tv); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::can_put (ACE_Message_Block *) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::can_put"); + assert (!"not implemented"); + return -1; +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::putq (ACE_Message_Block *mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::putq"); + return this->msg_queue_->enqueue_tail (mb, tv); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::ungetq (ACE_Message_Block *mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::ungetq"); + return this->msg_queue_->enqueue_head (mb, tv); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::is_reader (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::is_reader"); + return (ACE_BIT_ENABLED (this->flags_, ACE_Task_Flags::ACE_READER)); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::is_writer (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::is_writer"); + return (ACE_BIT_DISABLED (this->flags_, ACE_Task_Flags::ACE_READER)); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::flush (u_long flag) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::flush"); + if (ACE_BIT_ENABLED (flag, ACE_Task_Flags::ACE_FLUSHALL)) + return this->msg_queue_ != 0 && this->msg_queue_->close (); + else + return -1; // Note, need to be more careful about what we free... +} + +// Default ACE_Task service routine + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::svc (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::svc"); + return 0; +} + +template <ACE_SYNCH_1> ACE_INLINE ACE_Task<ACE_SYNCH_2> * +ACE_Task<ACE_SYNCH_2>::next (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::next"); + return this->next_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::next (ACE_Task<ACE_SYNCH_2> *q) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::next"); + this->next_ = q; +} + +template <ACE_SYNCH_1> ACE_INLINE ACE_Thread_Manager * +ACE_Task<ACE_SYNCH_2>::thr_mgr (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::thr_mgr"); + return this->thr_mgr_; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::thr_mgr (ACE_Thread_Manager *thr_mgr) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::thr_mgr"); + this->thr_mgr_ = thr_mgr; +} + +template <ACE_SYNCH_1> ACE_INLINE void +ACE_Task<ACE_SYNCH_2>::msg_queue (ACE_Message_Queue<ACE_SYNCH_2> *mq) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::msg_queue"); + this->msg_queue_ = mq; +} + +template <ACE_SYNCH_1> ACE_Message_Queue<ACE_SYNCH_2> * +ACE_Task<ACE_SYNCH_2>::msg_queue (void) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::msg_queue"); + return this->msg_queue_; +} + +// Transfer msg to the next ACE_Task. + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::put_next (ACE_Message_Block *msg, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::put_next"); + return this->next_ == 0 ? -1 : this->next_->put (msg, tv); +} + +template <ACE_SYNCH_1> ACE_INLINE int +ACE_Task<ACE_SYNCH_2>::reply (ACE_Message_Block *mb, ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Task<ACE_SYNCH_2>::reply"); + return this->sibling ()->put_next (mb, tv); +} + + diff --git a/ace/Thread.cpp b/ace/Thread.cpp new file mode 100644 index 00000000000..ad3cffca16e --- /dev/null +++ b/ace/Thread.cpp @@ -0,0 +1,68 @@ +// Thread.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Thread.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Thread.i" +#endif /* !defined (__ACE_INLINE__) */ + +#if defined (ACE_HAS_THREADS) + +int +ACE_Thread::spawn_n (size_t n, + ACE_THR_FUNC func, + void *arg, + long flags, + u_int priority, + void *stack[], + size_t stack_size[]) +{ + ACE_TRACE ("ACE_Thread::spawn_n"); + ACE_thread_t t_id; + size_t i; + + for (i = 0; i < n; i++) + // Bail out if error occurs. + if (ACE_OS::thr_create (func, arg, flags, &t_id, 0, priority, + stack == 0 ? 0 : stack[i], + stack_size == 0 ? 0 : stack_size[i]) != 0) + break; + + return i; +} + +int +ACE_Thread::spawn_n (ACE_thread_t thread_ids[], + size_t n, + ACE_THR_FUNC func, + void *arg, + long flags, + u_int priority, + void **stack, + size_t stack_size[]) +{ + ACE_TRACE ("ACE_Thread::spawn_n"); + size_t i; + + for (i = 0; i < n; i++) + { + ACE_thread_t t_id; + + int result = ACE_OS::thr_create + (func, arg, flags, &t_id, 0, priority, + stack == 0 ? 0 : stack[i], + stack_size == 0 ? 0 : stack_size[i]); + + if (result == 0) + thread_ids[i] = t_id; + else + // Bail out if error occurs. + break; + } + + return i; +} + +#endif /* ACE_HAS_THREADS */ diff --git a/ace/Thread.h b/ace/Thread.h new file mode 100644 index 00000000000..0d90998570b --- /dev/null +++ b/ace/Thread.h @@ -0,0 +1,183 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Thread.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_THREAD_H) +#define ACE_THREAD_H + +#include "ace/ACE.h" + +#if !defined (ACE_HAS_THREADS) +class ACE_Export ACE_Thread +{ +public: + static ACE_thread_t self (void); + // Return the unique ID of the thread. + + static void self (ACE_hthread_t &t_id); + // Return the unique kernel ID of the thread. + + static void exit (void *status = 0); + // Exit the current thread and return "status". + +private: + ACE_Thread (void); + // Ensure that we don't get instantiated. +}; +#else +class ACE_Export ACE_Thread +{ + // = TITLE + // Provides a wrapper for threads. + // + // = DESCRIPTION + // This class provides a common interface that is mapped onto + // either POSIX Pthreads, Solaris threads, or Win32 threads. + +public: + static int spawn (ACE_THR_FUNC func, + void *arg = 0, + long flags = THR_NEW_LWP, + ACE_thread_t *t_id = 0, + ACE_hthread_t *t_handle = 0, + u_int priority = 0, + void *stack = 0, + size_t stack_size = 0); + // Spawn a new thread, which executes "func" with argument "arg". + + static int spawn_n (size_t n, + ACE_THR_FUNC func, + void *arg = 0, + long flags = THR_NEW_LWP, + u_int priority = 0, + void *stack[] = 0, + size_t stack_size[] = 0); + // Spawn N new threads, which execute <func> with argument <arg>. + // 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 + // <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...). + + static int spawn_n (ACE_thread_t thread_ids[], + size_t n, + ACE_THR_FUNC func, + void *arg, + long flags, + u_int priority = 0, + void *stack[] = 0, + size_t stack_size[] = 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 + // <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...). + + static int join (ACE_thread_t, + ACE_thread_t *, + void ** = 0); + // Wait for one or more threads to exit. + + static int join (ACE_hthread_t, + void ** = 0); + // Wait for one thread to exit. + + static int resume (ACE_hthread_t); + // Continue the execution of a previously suspended thread. + + static int suspend (ACE_hthread_t); + // Suspend the execution of a particular thread. + + static int kill (ACE_thread_t, int signum); + // Send a signal to the thread. + + static void yield (void); + // Yield the thread to another. + + static void self (ACE_hthread_t &t_id); + // Return the unique kernel ID of the thread. + + static ACE_thread_t self (void); + // Return the unique ID of the thread. + + static void exit (void *status = 0); + // Exit the current thread and return "status". + + static int getconcurrency (void); + // Get the LWP concurrency level of the process. + + static int setconcurrency (int new_level); + // Set the LWP concurrency level of the process. + + static int sigsetmask (int how, + const sigset_t *set, + sigset_t *oset = 0); + // Change and/or examine calling thread's signal mask. + + static int keycreate (ACE_thread_key_t *keyp, + void (*destructor)(void *value), + void * = 0); + // Allocates a <keyp> that is used to identify data that is specific + // to each thread in the process. The key is global to all threads + // in the process. + + static int keyfree (ACE_thread_key_t key); + // Free up the key so that other threads can reuse it. + + static int setspecific (ACE_thread_key_t key, + void *value); + // Bind value to the thread-specific data key, <key>, for the calling + // thread. + + static int getspecific (ACE_thread_key_t key, + void **valuep); + // Stores the current value bound to <key> for the calling thread + // into the location pointed to by <valuep>. + + static int disablecancel (struct cancel_state *old_state); + // Disable thread cancellation. + + static int enablecancel (struct cancel_state *old_state, + int flag); + // Enable thread cancellation. + + static int setcancelstate (struct cancel_state &new_state, + struct cancel_state *old_state); + // Set the cancellation state. + + static int cancel (ACE_thread_t t_id); + // Cancel a thread. + + static void testcancel (void); + // Test the cancel. + +private: + ACE_Thread (void); + // Ensure that we don't get instantiated. +}; +#endif /* ACE_HAS_THREADS */ + +#if defined (__ACE_INLINE__) +#include "ace/Thread.i" +#endif /* __ACE_INLINE__ */ +#endif /* ACE_THREAD_H */ diff --git a/ace/Thread.i b/ace/Thread.i new file mode 100644 index 00000000000..c2842516a02 --- /dev/null +++ b/ace/Thread.i @@ -0,0 +1,266 @@ +/* -*- C++ -*- */ +// $Id$ + +// Thread.i + +#if !defined (ACE_HAS_THREADS) + +ACE_INLINE ACE_thread_t +ACE_Thread::self (void) +{ +// ACE_TRACE ("ACE_Thread::self"); + return ACE_OS::thr_self (); +} + +ACE_INLINE void +ACE_Thread::self (ACE_hthread_t &t_id) +{ +// ACE_TRACE ("ACE_Thread::self"); + ACE_OS::thr_self (t_id); +} + +ACE_INLINE void +ACE_Thread::exit (void *status) +{ + ACE_TRACE ("ACE_Thread::exit"); + ACE_OS::exit (*((int *) status)); +} +#else + +// Allocates a <keyp> that is used to identify data that is specific +// to each thread in the process. The key is global to all threads in +// the process. + +ACE_INLINE int +ACE_Thread::keycreate (ACE_thread_key_t *keyp, + void (*destructor)(void *value), + void *inst) +{ + ACE_TRACE ("ACE_Thread::keycreate"); + return ACE_OS::thr_keycreate (keyp, destructor, inst); +} + +// Free up the key so that other threads can reuse it. + +ACE_INLINE int +ACE_Thread::keyfree (ACE_thread_key_t key) +{ + ACE_TRACE ("ACE_Thread::keyfree"); + return ACE_OS::thr_keyfree (key); +} + +// Bind value to the thread-specific data key, <key>, for the calling +// thread. + +ACE_INLINE int +ACE_Thread::setspecific (ACE_thread_key_t key, void *value) +{ + ACE_TRACE ("ACE_Thread::setspecific"); + return ACE_OS::thr_setspecific (key, value); +} + +// Stores the current value bound to <key> for the calling thread +// into the location pointed to by <valuep>. + +ACE_INLINE int +ACE_Thread::getspecific (ACE_thread_key_t key, void **valuep) +{ + ACE_TRACE ("ACE_Thread::getspecific"); + return ACE_OS::thr_getspecific (key, valuep); +} + +ACE_INLINE ACE_thread_t +ACE_Thread::self (void) +{ +// ACE_TRACE ("ACE_Thread::self"); + return ACE_OS::thr_self (); +} + +ACE_INLINE void +ACE_Thread::exit (void *status) +{ + ACE_TRACE ("ACE_Thread::exit"); + ACE_OS::thr_exit (status); +} + +ACE_INLINE void +ACE_Thread::yield (void) +{ + ACE_TRACE ("ACE_Thread::yield"); + ACE_OS::thr_yield (); +} + +ACE_INLINE int +ACE_Thread::spawn (ACE_THR_FUNC func, + void *arg, + long flags, + ACE_thread_t *t_id, + ACE_hthread_t *t_handle, + u_int priority, + void *stack, + size_t stack_size) +{ + ACE_TRACE ("ACE_Thread::spawn"); + return ACE_OS::thr_create (func, arg, flags, t_id, t_handle, + priority, stack, stack_size); +} + +ACE_INLINE int +ACE_Thread::resume (ACE_hthread_t t_id) +{ + ACE_TRACE ("ACE_Thread::resume"); + return ACE_OS::thr_continue (t_id); +} + +ACE_INLINE int +ACE_Thread::suspend (ACE_hthread_t t_id) +{ + ACE_TRACE ("ACE_Thread::suspend"); + return ACE_OS::thr_suspend (t_id); +} + +ACE_INLINE int +ACE_Thread::kill (ACE_thread_t t_id, int signum) +{ + ACE_TRACE ("ACE_Thread::kill"); + return ACE_OS::thr_kill (t_id, signum); +} + +ACE_INLINE int +ACE_Thread::join (ACE_thread_t wait_for, + ACE_thread_t *departed, + void **status) +{ + ACE_TRACE ("ACE_Thread::join"); + return ACE_OS::thr_join (wait_for, departed, status); +} + +ACE_INLINE int +ACE_Thread::join (ACE_hthread_t wait_for, + void **status) +{ + ACE_TRACE ("ACE_Thread::join"); + return ACE_OS::thr_join (wait_for, status); +} + +ACE_INLINE int +ACE_Thread::getconcurrency (void) +{ + ACE_TRACE ("ACE_Thread::getconcurrency"); + return ACE_OS::thr_getconcurrency (); +} + +ACE_INLINE int +ACE_Thread::setconcurrency (int new_level) +{ + ACE_TRACE ("ACE_Thread::setconcurrency"); + return ACE_OS::thr_setconcurrency (new_level); +} + +ACE_INLINE int +ACE_Thread::sigsetmask (int how, + const sigset_t *set, + sigset_t *oset) +{ + ACE_TRACE ("ACE_Thread::sigsetmask"); + return ACE_OS::thr_sigsetmask (how, set, oset); +} + +ACE_INLINE int +ACE_Thread::disablecancel (struct cancel_state *old_state) +{ + ACE_TRACE ("ACE_Thread::disablecancel"); + int old_cstate; + int retval; + if ((retval = ACE_OS::thr_setcancelstate (THR_CANCEL_DISABLE, + &old_cstate)) == 0) + if (old_state != 0) + { + ACE_OS::memset (old_state, 0, sizeof(old_state)); + old_state->cancelstate = old_cstate; + } + + return retval; +} + +ACE_INLINE int +ACE_Thread::enablecancel (struct cancel_state *old_state, + int flag) +{ + ACE_TRACE ("ACE_Thread::enablecancel"); + int old_cstate; + int old_ctype; + int retval; + + retval = ACE_OS::thr_setcancelstate (THR_CANCEL_ENABLE, &old_cstate); + + if (retval != 0) + return retval; + + retval = ACE_OS::thr_setcanceltype (flag, &old_ctype); + + if (retval != 0) + return retval; + + if (old_state != 0) + { + old_state->cancelstate = old_cstate; + old_state->canceltype = old_ctype; + } + + return 0; +} + +ACE_INLINE int +ACE_Thread::setcancelstate (struct cancel_state &new_state, + struct cancel_state *old_state) +{ + ACE_TRACE ("ACE_Thread::setcancelstate"); + int old_cstate; + int old_ctype; + + if (new_state.cancelstate != 0 + && ACE_OS::thr_setcancelstate (new_state.cancelstate, &old_cstate) == 0) + return -1; + + if (new_state.canceltype != 0 + && ACE_OS::thr_setcanceltype (new_state.canceltype, &old_ctype) == 0) + { + int o_cstate; + ACE_OS::thr_setcancelstate (old_cstate, &o_cstate); + return -1; + } + + if (old_state != 0) + { + old_state->cancelstate = old_cstate; + old_state->canceltype = old_ctype; + } + + return 0; +} + +ACE_INLINE int +ACE_Thread::cancel (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread::cancel"); + + return ACE_OS::thr_cancel (t_id); +} + +ACE_INLINE void +ACE_Thread::testcancel (void) +{ + ACE_TRACE ("ACE_Thread::testcancel"); + + ACE_OS::thr_testcancel (); +} + +ACE_INLINE void +ACE_Thread::self (ACE_hthread_t &t_id) +{ +// ACE_TRACE ("ACE_Thread::self"); + ACE_OS::thr_self (t_id); +} + +#endif /* !defined (ACE_HAS_THREADS) */ diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp new file mode 100644 index 00000000000..bad4f22aa2f --- /dev/null +++ b/ace/Thread_Manager.cpp @@ -0,0 +1,767 @@ +// Thread_Manager.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Thread_Manager.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Thread_Manager.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Control) +ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Manager) + +#if defined (ACE_HAS_THREADS) + +void +ACE_Thread_Manager::dump (void) const +{ + ACE_TRACE ("ACE_Thread_Manager::dump"); +} + +ACE_Thread_Descriptor::ACE_Thread_Descriptor (void) + : thr_id_ (ACE_OS::NULL_thread), + grp_id_ (0), + thr_state_ (ACE_THR_IDLE) +{ + ACE_TRACE ("ACE_Thread_Descriptor::ACE_Thread_Descriptor"); +} + +// Return the thread descriptor (indexed by ACE_thread_t). + +int +ACE_Thread_Manager::thread_descriptor_i (ACE_thread_t thr_id, + ACE_Thread_Descriptor &descriptor) +{ + ACE_TRACE ("ACE_Thread_Descriptor::thread_descriptor_i"); + + for (size_t i = 0; i < this->current_count_; i++) + if (ACE_OS::thr_equal (thr_id, this->thr_table_[i].thr_id_)) + { + descriptor = this->thr_table_[i]; + return 0; + } + + return -1; +} + +int +ACE_Thread_Manager::thread_descriptor (ACE_thread_t thr_id, + ACE_Thread_Descriptor &descriptor) +{ + ACE_TRACE ("ACE_Thread_Descriptor::thread_descriptor"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + return this->thread_descriptor_i (thr_id, descriptor); +} + +// Return the thread descriptor (indexed by ACE_hthread_t). + +int +ACE_Thread_Manager::hthread_descriptor_i (ACE_hthread_t thr_handle, + ACE_Thread_Descriptor &descriptor) +{ + ACE_TRACE ("ACE_Thread_Descriptor::hthread_descriptor_i"); + + for (size_t i = 0; i < this->current_count_; i++) + if (ACE_OS::thr_cmp (thr_handle, this->thr_table_[i].thr_handle_)) + { + descriptor = this->thr_table_[i]; + return 0; + } + + return -1; +} + +int +ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle, + ACE_Thread_Descriptor &descriptor) +{ + ACE_TRACE ("ACE_Thread_Descriptor::hthread_descriptor"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + return this->hthread_descriptor_i (thr_handle, descriptor); +} + +// Return the thread descriptor (indexed by ACE_hthread_t). + +int +ACE_Thread_Manager::thr_self (ACE_hthread_t &self) +{ + ACE_TRACE ("ACE_Thread_Descriptor::thr_self"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + // Try to get the cached HANDLE out of TSS to avoid lookup. + ACE_hthread_t *handle = ACE_LOG_MSG->thr_handle (); + + // Wasn't in the cache, so we'll have to look it up and cache it. + if (handle == 0) + { + ACE_Thread_Descriptor td; + ACE_thread_t id = ACE_OS::thr_self (); + + int i = this->thread_descriptor_i (id, td); + + if (i == -1) + return -1; + handle = &this->thr_table_[i].thr_handle_; + + // Update the TSS cache. + ACE_LOG_MSG->thr_handle (handle); + } + self = *handle; + return 0; +} + +int +ACE_Thread_Manager::resize (size_t size) +{ + ACE_TRACE ("ACE_Thread_Manager::resize"); + ACE_Thread_Descriptor *temp; + + ACE_NEW_RETURN (temp, ACE_Thread_Descriptor[size], -1); + + for (size_t i = 0; i < this->max_table_size_; i++) + temp[i] = this->thr_table_[i]; // Structure assignment. + + this->max_table_size_ = size; + + delete [] this->thr_table_; + + this->thr_table_ = temp; + return 0; +} + +// Create and initialize the table to keep track of the thread pool. + +int +ACE_Thread_Manager::open (size_t size) +{ + ACE_TRACE ("ACE_Thread_Manager::open"); + 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_Thread_Manager::ACE_Thread_Manager (size_t size) + : zero_cond_ (lock_), + max_table_size_ (0), + thr_table_ (0), + current_count_ (0), + grp_id_ (1) +{ + ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager"); + if (this->open (size) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Thread_Manager")); +} + +// Close up and release all resources. + +int +ACE_Thread_Manager::close (void) +{ + ACE_TRACE ("ACE_Thread_Manager::close"); + if (this->thr_table_ != 0) + { + delete [] this->thr_table_; + this->thr_table_ = 0; + this->max_table_size_ = 0; + this->current_count_ = 0; + } + return 0; +} + +ACE_Thread_Manager::~ACE_Thread_Manager (void) +{ + ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager"); + this->close (); +} + +// Call the appropriate OS routine to spawn a thread. Should *not* be +// called with the lock_ held... + +int +ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func, + void *args, + long flags, + ACE_thread_t *t_id, + ACE_hthread_t *t_handle, + u_int priority, + int grp_id, + void *stack, + size_t stack_size) +{ + ACE_TRACE ("ACE_Thread_Manager::spawn_i"); + ACE_thread_t thr_id; + ACE_hthread_t thr_handle; + + if (t_id == 0) + t_id = &thr_id; + + if (t_handle == 0) + t_handle = &thr_handle; + + int result = ACE_Thread::spawn (func, args, flags, + t_id, t_handle, priority, + stack, stack_size); + if (result != 0) + { + errno = result; + return -1; + } + else + return this->append_thr (*t_id, *t_handle, + ACE_THR_SPAWNED, + grp_id); +} + +// Create a new thread running FUNC. *Must* be called with the lock_ +// held... + +int +ACE_Thread_Manager::spawn (ACE_THR_FUNC func, + void *args, + long flags, + ACE_thread_t *t_id, + ACE_hthread_t *t_handle, + u_int priority, + int grp_id, + void *stack, + size_t stack_size) +{ + ACE_TRACE ("ACE_Thread_Manager::spawn"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + if (grp_id == -1) + grp_id = this->grp_id_++; // Increment the group id. + + if (this->spawn_i (func, args, flags, t_id, t_handle, + priority, grp_id, stack, stack_size) == -1) + return -1; + else + return grp_id; +} + +// Create N new threads running FUNC. + +int +ACE_Thread_Manager::spawn_n (int n, + ACE_THR_FUNC func, + void *args, + long flags, + u_int priority, + int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::spawn_n"); + 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, 0, 0, priority, grp_id) == -1) + return -1; + } + + return grp_id; +} + +// Append a thread into the pool (does not check for duplicates). +// Must be called with locks held. + +int +ACE_Thread_Manager::append_thr (ACE_thread_t t_id, + ACE_hthread_t t_handle, + ACE_Thread_State thr_state, + int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::append_thr"); + // 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 &thr_desc = + this->thr_table_[this->current_count_]; + + thr_desc.thr_id_ = t_id; + thr_desc.thr_handle_ = t_handle; + thr_desc.grp_id_ = grp_id; + thr_desc.thr_state_ = thr_state; + + this->current_count_++; + return 0; + } +} + +// Insert a thread into the pool (checks for duplicates and doesn't +// allow them to be inserted twice). + +int +ACE_Thread_Manager::insert_thr (ACE_thread_t t_id, + ACE_hthread_t t_handle, + int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::insert_thr"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + // Check for duplicates and bail out if they're already + // registered... + if (this->find (t_id) != -1) + return -1; + + if (grp_id == -1) + grp_id = this->grp_id_++; + + if (this->append_thr (t_id, t_handle, + ACE_THR_SPAWNED, + grp_id) == -1) + return -1; + else + return grp_id; +} + +// Remove a thread from the pool. Must be called with locks held. + +void +ACE_Thread_Manager::remove_thr (int i) +{ + ACE_TRACE ("ACE_Thread_Manager::remove_thr"); + if (this->current_count_ > 1) + // Structure assignment. + this->thr_table_[i] = this->thr_table_[this->current_count_ - 1]; + + this->current_count_--; + + // Tell all waiters when there are no more threads left in the pool. + if (this->current_count_ == 0) + this->zero_cond_.broadcast (); +} + +// Factory out some common behavior to simplify the following methods. +#define ACE_THR_OP(OP,STATE) \ + int result = OP (this->thr_table_[i].thr_handle_); \ + if (result != 0) { \ + this->remove_thr (i); \ + errno = result; \ + return -1; \ + } \ + else { \ + this->thr_table_[i].thr_state_ = STATE; \ + return 0; \ + } + +int +ACE_Thread_Manager::suspend_thr (int i) +{ + ACE_TRACE ("ACE_Thread_Manager::suspend_thr"); + + ACE_THR_OP (ACE_Thread::suspend, ACE_THR_SUSPENDED); +} + +int +ACE_Thread_Manager::resume_thr (int i) +{ + ACE_TRACE ("ACE_Thread_Manager::resume_thr"); + + ACE_THR_OP (ACE_Thread::resume, ACE_THR_RUNNING); +} + +int +ACE_Thread_Manager::cancel_thr (int i) +{ + ACE_TRACE ("ACE_Thread_Manager::cancel_thr"); + this->thr_table_[i].thr_state_ = ACE_THR_CANCELLED; + return 0; +} + +int +ACE_Thread_Manager::kill_thr (int i, int signum) +{ + ACE_TRACE ("ACE_Thread_Manager::kill_thr"); + + int result = ACE_Thread::kill ((ACE_thread_t) this->thr_table_[i].thr_handle_, + signum); + + if (result != 0) + { + this->remove_thr (i); + errno = result; + return -1; + } + else + return 0; +} + +// Locate the index in the table associated with <t_id>. Must be +// called with the lock held. + +int +ACE_Thread_Manager::find (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::find"); + + for (size_t i = 0; i < this->current_count_; i++) + if (ACE_OS::thr_equal (t_id, this->thr_table_[i].thr_id_)) + return i; + + return -1; +} + +#define ACE_EXECUTE_OP(OP) \ + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); \ + int i = this->find (t_id); \ + if (i == -1) return -1; \ + return OP (i); + +// Suspend a single thread. + +int +ACE_Thread_Manager::suspend (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::suspend"); + ACE_EXECUTE_OP (this->suspend_thr); +} + +// Resume a single thread. + +int +ACE_Thread_Manager::resume (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::resume"); + ACE_EXECUTE_OP (this->resume_thr); +} + +// Cancel a single thread. + +int +ACE_Thread_Manager::cancel (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::cancel"); + ACE_EXECUTE_OP (this->cancel_thr); +} + +// Send a signal to a single thread. + +int +ACE_Thread_Manager::kill (ACE_thread_t t_id, int signum) +{ + ACE_TRACE ("ACE_Thread_Manager::kill"); + return ACE_Thread::kill (t_id, signum); +} + +int +ACE_Thread_Manager::check_state (ACE_Thread_State state, + ACE_thread_t id) +{ + ACE_TRACE ("ACE_Thread_Manager::check_state"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + ACE_Thread_State *thr_state = 0; +#if 0 + int self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ()); + + // If we're checking the state of our thread, try to get the cached + // value out of TSS to avoid lookup. + if (self_check) + thr_state = ACE_LOG_MSG->thr_state (); + + // Wasn't in the cache, so we'll have to look it up. + if (thr_state == 0) + { + int i = this->find (id); + + if (i == -1) + return -1; + thr_state = &this->thr_table_[i].thr_state_; + + if (self_check) // Update the TSS cache. + ACE_LOG_MSG->thr_state (thr_state); + } +#else + // Turn off caching for the time being until we figure out + // how to do it correctly in the face of deletions... + int i = this->find (id); + + if (i == -1) + return -1; + thr_state = &this->thr_table_[i].thr_state_; +#endif /* 0 */ + return *thr_state == state; +} + +// Test if a single thread is suspended. + +int +ACE_Thread_Manager::testsuspend (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::testsuspend"); + return this->check_state (ACE_THR_SUSPENDED, t_id); +} + +// Test if a single thread is active (i.e., resumed). + +int +ACE_Thread_Manager::testresume (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::testresume"); + return this->check_state (ACE_THR_RUNNING, t_id); +} + +// Test if a single thread is cancelled. + +int +ACE_Thread_Manager::testcancel (ACE_thread_t t_id) +{ + ACE_TRACE ("ACE_Thread_Manager::testcancel"); + return this->check_state (ACE_THR_CANCELLED, t_id); +} + +// Get group ids for a particular thread id. + +int +ACE_Thread_Manager::get_grp (ACE_thread_t t_id, int &grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::get_grp"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + int i = this->find (t_id); + if (i == -1) + return -1; + grp_id = this->thr_table_[i].grp_id_; + return 0; +} + +// Set group ids for a particular thread id. + +int +ACE_Thread_Manager::set_grp (ACE_thread_t t_id, int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::set_grp"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + int i = this->find (t_id); + if (i == -1) + return -1; + this->thr_table_[i].grp_id_ = grp_id; + return 0; +} + +// Suspend a group of threads. + +int +ACE_Thread_Manager::apply_grp (int grp_id, + THR_FUNC func, + int arg) +{ + ACE_TRACE ("ACE_Thread_Manager::apply_grp"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + int result = 0; + + for (size_t i = 0; i < this->current_count_; i++) + if (this->thr_table_[i].grp_id_ == grp_id + && (this->*func)(i, arg) == -1) + result = -1; + + return result; +} + +int +ACE_Thread_Manager::suspend_grp (int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::suspend_grp"); + return this->apply_grp (grp_id, + THR_FUNC (&ACE_Thread_Manager::suspend_thr)); +} + +// Resume a group of threads. + +int +ACE_Thread_Manager::resume_grp (int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::resume_grp"); + return this->apply_grp (grp_id, + THR_FUNC (&ACE_Thread_Manager::resume_thr)); +} + +// Kill a group of threads. + +int +ACE_Thread_Manager::kill_grp (int grp_id, int signum) +{ + ACE_TRACE ("ACE_Thread_Manager::kill_grp"); + return this->apply_grp (grp_id, + THR_FUNC (&ACE_Thread_Manager::kill_thr), signum); +} + +// Cancel a group of threads. + +int +ACE_Thread_Manager::cancel_grp (int grp_id) +{ + ACE_TRACE ("ACE_Thread_Manager::resume_grp"); + return this->apply_grp (grp_id, + THR_FUNC (&ACE_Thread_Manager::cancel_thr)); +} + +int +ACE_Thread_Manager::apply_all (THR_FUNC func, int arg) +{ + ACE_TRACE ("ACE_Thread_Manager::apply_all"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + int result = 0; + + for (size_t i = 0; i < this->current_count_; i++) + if ((this->*func)(i, arg) == -1) + result = -1; + + return result; +} + +// Resume all threads that are suspended. + +int +ACE_Thread_Manager::resume_all (void) +{ + ACE_TRACE ("ACE_Thread_Manager::resume_all"); + return this->apply_all (THR_FUNC (&ACE_Thread_Manager::resume_thr)); +} + +int +ACE_Thread_Manager::suspend_all (void) +{ + ACE_TRACE ("ACE_Thread_Manager::suspend_all"); + return this->apply_all (THR_FUNC (&ACE_Thread_Manager::suspend_thr)); +} + +int +ACE_Thread_Manager::kill_all (int sig) +{ + ACE_TRACE ("ACE_Thread_Manager::kill_all"); + return this->apply_all (&ACE_Thread_Manager::kill_thr, sig); +} + +int +ACE_Thread_Manager::cancel_all (void) +{ + ACE_TRACE ("ACE_Thread_Manager::cancel_all"); + return this->apply_all (THR_FUNC (&ACE_Thread_Manager::cancel_thr)); +} + +// Must be called when thread goes out of scope to clean up its table +// slot. + +void * +ACE_Thread_Manager::exit (void *status, int do_thr_exit) +{ + ACE_TRACE ("ACE_Thread_Manager::exit"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0); + + int i = this->find (ACE_Thread::self ()); + + // Locate thread id. + if (i != -1) + this->remove_thr (i); + + if (do_thr_exit) + { + // Note, destructor is never called, so we must manually release + // the lock... + + ACE_MT (ace_mon.release ()); + + ACE_Thread::exit (status); + // On reasonable systems ACE_Thread::exit() should not return. + // However, due to horrible semantics with Win32 thread-specific + // storage this call can return (don't ask...). Therefore, we + // need to reacquire the mutex so that we don't get burned when + // the Guard automatically releases it when this method returns. + ACE_MT (ace_mon.acquire ()); + } + return 0; +} + +// Wait for all the threads to exit. + +int +ACE_Thread_Manager::wait (const ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_Thread_Manager::wait"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + while (this->current_count_ > 0) + if (this->zero_cond_.wait (timeout) == -1) + return -1; + + return 0; +} + +void +ACE_Thread_Control::dump (void) const +{ + ACE_TRACE ("ACE_Thread_Control::dump"); +} + +int +ACE_Thread_Control::insert (ACE_Thread_Manager *tm) +{ + ACE_TRACE ("ACE_Thread_Control::insert"); + + ACE_hthread_t t_id; + ACE_Thread::self (t_id); + this->tm_ = tm; + + return this->tm_->insert_thr (ACE_Thread::self (), t_id); +} + +// Initialize the thread controller. + +ACE_Thread_Control::ACE_Thread_Control (ACE_Thread_Manager *t, + int insert) + : tm_ (t), + status_ (0) +{ + ACE_TRACE ("ACE_Thread_Control::ACE_Thread_Control"); + if (this->tm_ != 0 && insert) + { + ACE_hthread_t t_id; + ACE_Thread::self (t_id); + this->tm_->insert_thr (ACE_Thread::self (), t_id); + } +} + +// Automatically kill thread on exit. + +ACE_Thread_Control::~ACE_Thread_Control (void) +{ + ACE_TRACE ("ACE_Thread_Control::~ACE_Thread_Control"); + this->exit (this->status_); +} + +// Exit from thread (but clean up first). + +void * +ACE_Thread_Control::exit (void *exit_status) +{ + ACE_TRACE ("ACE_Thread_Control::exit"); + if (this->tm_ != 0) + return this->tm_->exit (exit_status); + else + { + ACE_Thread::exit (exit_status); + return 0; + } +} + +#endif /* !defined (ACE_HAS_THREADS) */ diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h new file mode 100644 index 00000000000..ca1b8b4125e --- /dev/null +++ b/ace/Thread_Manager.h @@ -0,0 +1,403 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Thread_Manager.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_THREAD_MANAGER_H) +#define ACE_THREAD_MANAGER_H + +#include "ace/Log_Msg.h" +#include "ace/Thread.h" +#include "ace/Synch.h" + +class ACE_Thread_Manager; + +class ACE_Export ACE_Thread_Descriptor + // = Title + // Information for controlling threads that run under the control + // of the <Thread_Manager>. +{ +friend class ACE_Thread_Manager; +public: + // = Initialization method. + ACE_Thread_Descriptor (void); + + // = Accessor methods. + ACE_thread_t self (void); + // Unique thread id. + + void self (ACE_hthread_t &); + // Unique handle to thread (used by Win32 and AIX). + + int grp_id (void); + // Group ID. + + ACE_Thread_State state (void); + // Current state of the thread. + +private: + + ACE_thread_t thr_id_; + // Unique thread ID. + + ACE_hthread_t thr_handle_; + // Unique handle to thread (used by Win32 and AIX). + + int grp_id_; + // Group ID. + + ACE_Thread_State thr_state_; + // Current state of the thread. +}; + +#if !defined (ACE_HAS_THREADS) + +class ACE_Export ACE_Thread_Manager +{ +public: + enum + { + DEFAULT_SIZE = 100 + }; + + ACE_Thread_Manager (int = 0) {} + ~ACE_Thread_Manager (void) {} + + int open (size_t = DEFAULT_SIZE) { return -1; } + int close (void) { return -1; } + int spawn (ACE_THR_FUNC, + void * = 0, + long = 0, + ACE_thread_t * = 0, + ACE_hthread_t * = 0, + u_int = 0, + int = -1, + void * = 0, + size_t = 0) { return -1;} + int spawn_n (int, + ACE_THR_FUNC, + void * = 0, + long = 0, + u_int = 0, + int = -1) { return -1;} + void *exit (void *) { return 0; } + void wait (const ACE_Time_Value * = 0) {} + int thread_descriptor (ACE_thread_t, ACE_Thread_Descriptor &) { return -1;} + int hthread_descriptor (ACE_hthread_t, ACE_Thread_Descriptor &) { return -1;} + int suspend_all (void) { return -1; } + int suspend (ACE_thread_t) { return -1; } + int suspend_grp (ACE_thread_t) { return -1; } + int resume_all (void) { return -1; } + int resume (ACE_thread_t) { return -1; } + int resume_grp (ACE_thread_t) { return -1; } + int kill_all (int) { return -1; } + int kill (ACE_thread_t) { return -1; } + int kill_grp (ACE_thread_t) { return -1; } + int cancel_all (void) { return -1; } + int cancel (int) { return -1; } + int cancel_grp (int) { return -1; } + void dump (void) const { } +}; + +class ACE_Export ACE_Thread_Control +{ +public: + ACE_Thread_Control (ACE_Thread_Manager * = 0, int = 0) {} + ~ACE_Thread_Control (void) {} + ACE_Thread_Manager *thr_mgr (void) { return 0; } + ACE_Thread_Manager *thr_mgr (ACE_Thread_Manager *) { return 0; } + void *exit (void *) { return 0; } + int insert (ACE_Thread_Manager *) { return 0; } + void *status (void *) { return 0; } + void *status (void) { return 0; } + void dump (void) const { } +}; +#else + +// Forward declaration. +class ACE_Thread_Control; + +class ACE_Export ACE_Thread_Manager + // = TITLE + // Manages a pool of threads. + // + // = DESCRIPTION + // This class allows operations on groups of threads atomically. +{ +friend class ACE_Thread_Control; +public: + enum + { + DEFAULT_SIZE = 100 + }; + + // = Initialization and termination methods. + ACE_Thread_Manager (size_t size = ACE_Thread_Manager::DEFAULT_SIZE); + ~ACE_Thread_Manager (void); + + int open (size_t size = DEFAULT_SIZE); + // Initialize the manager with room for SIZE threads. + + int close (void); + // Release all resources. + + int spawn (ACE_THR_FUNC func, + void *args = 0, + long flags = THR_NEW_LWP, + ACE_thread_t * = 0, + ACE_hthread_t *t_handle = 0, + u_int priority = 0, + int grp_id = -1, + void *stack = 0, + size_t stack_size = 0); + // Create a new thread, which executes <func>. + + // 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, + ACE_THR_FUNC func, + void *args = 0, + long flags = THR_NEW_LWP, + u_int priority = 0, + int grp_id = -1); + // Create N new threads, all of which execute <func>. + + // 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. + + 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 + // which case <status> is passed as the exit value of the thread. + + int wait (const ACE_Time_Value *timeout = 0); + // Block until there are no more threads running in the + // <Thread_Manager> or <timeout> expires. Returns 0 on success and + // -1 on failure. + + // = Accessors for <ACE_Thread_Descriptors>. + int thread_descriptor (ACE_thread_t, ACE_Thread_Descriptor &); + // Return the thread descriptor (indexed by ACE_thread_t). Returns 0 on + // success and -1 if not found. + + int hthread_descriptor (ACE_hthread_t, ACE_Thread_Descriptor &); + // Return the thread descriptor (indexed by ACE_hthread_t). Returns 0 + // on success and -1 if not found. + + int thr_self (ACE_hthread_t &); + // Passes out the "real" handle to the thread, caching it if + // necessary in TSS to speed up subsequent lookups. + + // = Suspend methods, which isn't supported on POSIX pthreads (will + // not block). + int suspend_all (void); + // Suspend all threads + int suspend (ACE_thread_t); + // Suspend a single thread. + int suspend_grp (int grp_id); + // Suspend a group of threads. + int testsuspend (ACE_thread_t t_id); + // True if <t_id> is inactive (i.e., suspended), else false. + + // = Resume methods, which isn't supported on POSIX pthreads (will + // not block). + int resume_all (void); + // Resume all stopped threads + int resume (ACE_thread_t); + // Resume a single thread. + int resume_grp (int grp_id); + // Resume a group of threads. + int testresume (ACE_thread_t t_id); + // True if <t_id> is active (i.e., resumed), else false. + + // = Kill methods, send signals -- which isn't supported on Win32 + // (will not block). + int kill_all (int signum); + // Send signum to all stopped threads + int kill (ACE_thread_t, int signum); + // Kill a single thread. + int kill_grp (int grp_id, int signum); + // Kill a group of threads. + + // = Cancel methods, which provides a cooperative thread-termination + // mechanism (will not block). + int cancel_all (void); + // Send signum to all stopped threads + int cancel (ACE_thread_t); + // Cancel a single thread. + int cancel_grp (int grp_id); + // Cancel a group of threads. + int testcancel (ACE_thread_t t_id); + // True if <t_id> is cancelled, else false. + + // = Set/get group ids for a particular thread id. + int set_grp (ACE_thread_t, int grp_id); + int get_grp (ACE_thread_t, int &grp_id); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + int resize (size_t); + // Resize the pool of Thread_Descriptors. + + int spawn_i (ACE_THR_FUNC func, + void *args, + long flags, + ACE_thread_t * = 0, + ACE_hthread_t *t_handle = 0, + u_int priority = 0, + int grp_id = -1, + void *stack = 0, + size_t stack_size = 0); + // Create a new thread (must be called with locks held). + + int find (ACE_thread_t t_id); + // Locate the index of the table slot occupied by <t_id>. Returns + // -1 if <t_id> is not in the table doesn't contain <t_id>. + + int insert_thr (ACE_thread_t t_id, ACE_hthread_t, int grp_id = -1); + // Insert a thread in the table (checks for duplicates). + + int append_thr (ACE_thread_t t_id, ACE_hthread_t, + ACE_Thread_State, + int grp_id); + // Append a thread in the table (adds at the end, growing the table + // if necessary). + + void remove_thr (int i); + // Remove thread from the table. + + int thread_descriptor_i (ACE_thread_t, ACE_Thread_Descriptor &); + // Implements the lookup function for the <thread_descriptor>. Note + // that this version assumes that the lock is held. We need this to + // avoid intra-class method deadlock on systems that lack recursive + // mutexes. + + int hthread_descriptor_i (ACE_hthread_t, ACE_Thread_Descriptor &); + // Implements the lookup function for the <hthread_descriptor>. + // Note that this version assumes that the lock is held. We need + // this to avoid intra-class method deadlock on systems that lack + // recursive mutexes. + + // = The following four methods implement a simple scheme for + // operating on a collection of threads atomically. + + typedef int (ACE_Thread_Manager::*THR_FUNC)(int, int); + + int check_state (ACE_Thread_State state, ACE_thread_t thread); + // Efficiently check whether <thread> is in a particular <state>. + // This call updates the TSS cache if possible to speed up + // subsequent searches. + + int apply_grp (int grp_id, THR_FUNC, int = 0); + // Apply <func> to all members of the table that match the <grp_id>. + + int apply_all (THR_FUNC, int = 0); + // Apply <func> to all members of the table. + + int resume_thr (int i); + // Resume the thread at index <i>. + + int suspend_thr (int i); + // Suspend the thread at index <i>. + + int kill_thr (int i, int signum); + // Send signal <signum> to the thread at index <i>. + + int cancel_thr (int i); + // Set the cancellation flag for the thread at index <i>. + + ACE_Thread_Descriptor *thr_table_; + // Vector that describes thread state within the Thread_Manager. + + size_t max_table_size_; + // Maximum number of threads we can manage (should be dynamically + // allocated). + + size_t current_count_; + // Current number of threads we are managing. + + int grp_id_; + // Keeps track of the next group id to assign. + + // = ACE_Thread_Mutex and condition variable for synchronizing + // termination. + ACE_Thread_Mutex lock_; + ACE_Condition_Thread_Mutex zero_cond_; +}; + + +class ACE_Export ACE_Thread_Control + // = TITLE + // Used to keep track of a thread's activities within its entry + // point function. +{ +public: + ACE_Thread_Control (ACE_Thread_Manager *tm = 0, + int insert = 0); + // Initialize the thread control object. If <insert> != 0, then + // register the thread with the Thread_Manager. + + ~ACE_Thread_Control (void); + // Implicitly kill the thread on exit and remove it from its + // associated ThreadManager. + + void *exit (void *status); + // Explicitly kill the thread on exit and remove it from its + // associated <Thread_Manager>. + + int insert (ACE_Thread_Manager *tm); + // Store the <Thread_Manager> and use it to register ourselves for + // correct shutdown. + + ACE_Thread_Manager *thr_mgr (void); + // Returns the current <Thread_Manager>. + + ACE_Thread_Manager *thr_mgr (ACE_Thread_Manager *); + // Atomically set a new <Thread_Manager> and return the old + // <Thread_Manager>. + + void *status (void *status); + // Set the exit status (and return existing status). + + void *status (void); + // Get the current exit status. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Thread_Manager *tm_; + // Pointer to the thread manager for this block of code. + + void *status_; + // Keeps track of the exit status for the thread. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Thread_Manager.i" +#endif /* __ACE_INLINE__ */ + +#endif /* !defined (ACE_HAS_THREADS) */ +#endif /* ACE_THREAD_MANAGER_H */ + diff --git a/ace/Thread_Manager.i b/ace/Thread_Manager.i new file mode 100644 index 00000000000..041b74cea66 --- /dev/null +++ b/ace/Thread_Manager.i @@ -0,0 +1,83 @@ +/* -*- C++ -*- */ +// $Id$ + +// Thread_Manager.i + +#include "ace/Log_Msg.h" + +// Unique thread id. +ACE_INLINE ACE_thread_t +ACE_Thread_Descriptor::self (void) +{ + ACE_TRACE ("ACE_Thread_Descriptor::self"); + return this->thr_id_; +} + +// Unique kernel-level thread handle. + +ACE_INLINE void +ACE_Thread_Descriptor::self (ACE_hthread_t &handle) +{ + ACE_TRACE ("ACE_Thread_Descriptor::self"); + handle = this->thr_handle_; +} + +// Group ID. + +ACE_INLINE int +ACE_Thread_Descriptor::grp_id (void) +{ + ACE_TRACE ("ACE_Thread_Descriptor::grp_id"); + return grp_id_; +} + +// Current state of the thread. +ACE_INLINE ACE_Thread_State +ACE_Thread_Descriptor::state (void) +{ + ACE_TRACE ("ACE_Thread_Descriptor::state"); + return thr_state_; +} + +#if defined (ACE_HAS_THREADS) + +// Set the exit status. + +ACE_INLINE void * +ACE_Thread_Control::status (void *s) +{ + ACE_TRACE ("ACE_Thread_Control::status"); + return this->status_ = s; +} + +// Get the exit status. + +ACE_INLINE void * +ACE_Thread_Control::status (void) +{ + ACE_TRACE ("ACE_Thread_Control::status"); + return this->status_; +} + +// Returns the current <Thread_Manager>. + +ACE_INLINE ACE_Thread_Manager * +ACE_Thread_Control::thr_mgr (void) +{ + ACE_TRACE ("ACE_Thread_Control::thr_mgr"); + return this->tm_; +} + +// Atomically set a new <Thread_Manager> and return the old +// <Thread_Manager>. + +ACE_INLINE ACE_Thread_Manager * +ACE_Thread_Control::thr_mgr (ACE_Thread_Manager *tm) +{ + ACE_TRACE ("ACE_Thread_Control::thr_mgr"); + ACE_Thread_Manager *o_tm = this->tm_; + return this->tm_ = tm; + return o_tm; +} + +#endif /* !defined (ACE_HAS_THREADS) */ diff --git a/ace/Time_Request_Reply.cpp b/ace/Time_Request_Reply.cpp new file mode 100644 index 00000000000..46bce6553c6 --- /dev/null +++ b/ace/Time_Request_Reply.cpp @@ -0,0 +1,187 @@ +// Time_Request_Reply.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Time_Request_Reply.h" + +// Default "do nothing" constructor. + +ACE_Time_Request::ACE_Time_Request (void) +{ + ACE_TRACE ("ACE_Time_Request::ACE_Time_Request"); +} + +// Create a ACE_Time_Request message. + +ACE_Time_Request::ACE_Time_Request (ACE_UINT32 t, // Type of request. + const ACE_UINT32 time, + ACE_Time_Value *timeout) // Max time waiting for request. +{ + ACE_TRACE ("ACE_Time_Request::ACE_Time_Request"); + this->msg_type (t); + + // If timeout is a NULL pointer, then block forever... + if (timeout == 0) + { + this->transfer_.block_forever_ = 1; + this->transfer_.sec_timeout_ = 0; + this->transfer_.usec_timeout_ = 0; + } + else // Do a "timed wait." + { + this->block_forever (0); + // Keep track of how long client is willing to wait. + this->transfer_.sec_timeout_ = timeout->sec (); + this->transfer_.usec_timeout_ = timeout->usec (); + } + + // Copy time into request + this->time_ = this->transfer_.time_ = time; +} + +// Initialize length_ in order to avoid problems with byte-ordering +void +ACE_Time_Request::init (void) +{ + ACE_TRACE ("ACE_Time_Request::init"); +// this->length (sizeof this->transfer_); +} + +// Get the fixed size of message +ssize_t +ACE_Time_Request::size (void) const +{ + ACE_TRACE ("ACE_Time_Request::size"); + return sizeof (this->transfer_); +} + +// = Set/get the type of the message. +ACE_UINT32 +ACE_Time_Request::msg_type (void) const +{ + ACE_TRACE ("ACE_Time_Request::msg_type"); + return this->transfer_.msg_type_; +} + +void +ACE_Time_Request::msg_type (ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Time_Request::msg_type"); + this->transfer_.msg_type_ = t; +} + +// = Set/get the blocking semantics. +ACE_UINT32 +ACE_Time_Request::block_forever (void) const +{ + ACE_TRACE ("ACE_Time_Request::block_forever"); + return this->transfer_.block_forever_; +} + +void +ACE_Time_Request::block_forever (ACE_UINT32 bs) +{ + ACE_TRACE ("ACE_Time_Request::block_forever"); + this->transfer_.block_forever_ = bs; +} + +// = Set/get the timeout. +ACE_Time_Value +ACE_Time_Request::timeout (void) const +{ + ACE_TRACE ("ACE_Time_Request::timeout"); + return ACE_Time_Value (this->transfer_.sec_timeout_, this->transfer_.usec_timeout_); +} + +void +ACE_Time_Request::timeout (const ACE_Time_Value timeout) +{ + ACE_TRACE ("ACE_Time_Request::timeout"); + this->transfer_.sec_timeout_ = timeout.sec (); + this->transfer_.usec_timeout_ = timeout.usec (); +} + +// = Set/get the time +const ACE_UINT32 +ACE_Time_Request::time (void) const +{ + ACE_TRACE ("ACE_Time_Request::time"); + return this->time_; +} + +void +ACE_Time_Request::time (const ACE_UINT32 t) +{ + ACE_TRACE ("ACE_Time_Request::time"); + this->time_ = t; +} + +// Encode the transfer buffer into network byte order +// so that it can be sent to the server. +int +ACE_Time_Request::encode (void *&buf) +{ + ACE_TRACE ("ACE_Time_Request::encode"); + // Compute the length *before* doing the marshaling. + + buf = (void *) &this->transfer_; + this->transfer_.block_forever_ = htonl (this->transfer_.block_forever_); + this->transfer_.usec_timeout_ = htonl (this->transfer_.usec_timeout_); + this->transfer_.sec_timeout_ = htonl (this->transfer_.sec_timeout_); + this->transfer_.msg_type_ = htonl (this->transfer_.msg_type_); + this->transfer_.time_ = htonl (this->transfer_.time_); + + return this->size (); // Always fixed +} + +// Decode the transfer buffer into host byte byte order +// so that it can be used by the server. +int +ACE_Time_Request::decode (void) +{ + ACE_TRACE ("ACE_Time_Request::decode"); + // Decode + this->transfer_.block_forever_ = ntohl (this->transfer_.block_forever_); + this->transfer_.usec_timeout_ = ntohl (this->transfer_.usec_timeout_); + this->transfer_.sec_timeout_ = ntohl (this->transfer_.sec_timeout_); + this->transfer_.msg_type_ = ntohl (this->transfer_.msg_type_); + this->transfer_.time_ = ntohl (this->transfer_.time_); + + this->time_ = this->transfer_.time_; + return 0; +} + +// Print out the current values of the ACE_Time_Request. + +void +ACE_Time_Request::dump (void) const +{ + ACE_TRACE ("ACE_Time_Request::dump"); + ACE_DEBUG ((LM_DEBUG, "*******\nlength = %d\n", + this->size ())); + ACE_DEBUG ((LM_DEBUG, "message-type = ")); + + switch (this->msg_type ()) + { + case ACE_Time_Request::TIME_UPDATE: + ACE_DEBUG ((LM_DEBUG, "TIME_UPDATE\n")); + break; + default: + ACE_DEBUG ((LM_DEBUG, "<unknown type> = %d\n", this->msg_type ())); + break; + } + + if (this->block_forever ()) + ACE_DEBUG ((LM_DEBUG, "blocking forever\n")); + else + { + ACE_Time_Value tv = this->timeout (); + ACE_DEBUG ((LM_DEBUG, "waiting for %ld secs and %ld usecs\n", + tv.sec (), tv.usec ())); + } + ACE_DEBUG ((LM_DEBUG, "*******\ntime = %d\n", + this->time ())); + ACE_DEBUG ((LM_DEBUG, "+++++++\n")); +} + diff --git a/ace/Time_Request_Reply.h b/ace/Time_Request_Reply.h new file mode 100644 index 00000000000..7bd3219d6e7 --- /dev/null +++ b/ace/Time_Request_Reply.h @@ -0,0 +1,119 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Time_Request_Reply.h +// +// = DESCRIPTION +// Define the format used to exchange messages between the +// ACE_Time_Server and clerks. +// +// = AUTHOR +// Prashant Jain +// +// ============================================================================ + +#if !defined (ACE_TIME_REQUEST_REPLY_H) +#define ACE_TIME_REQUEST_REPLY_H + +#include "ace/Time_Value.h" +#include "ace/SString.h" + +class ACE_Export ACE_Time_Request + // = TITLE + // Message format for delivering requests to the ACE_Time Server. + // + // = DESCRIPTION + // This class is implemented to minimize data copying. + // In particular, all marshaling is done in situ... +{ +public: + enum Constants + { + // Request message types. + TIME_UPDATE = 01, + FAILURE = 05, + + // Class-specific constant values. + MAX_TIME_LEN = MAXPATHLEN + 1 + }; + + ACE_Time_Request (void); + // Default constructor. + + ACE_Time_Request (ACE_UINT32 msg_type, // Type of request. + const ACE_UINT32 time, + ACE_Time_Value *timeout = 0); // Max time waiting for request. + // Create a <ACE_Time_Request> message. + + void init (void); + // Initialize length_ in order to ensure correct byte ordering + // before a request is sent. + + // Get the fixed size of message + ssize_t size (void) const; + + // = Set/get the type of the message. + ACE_UINT32 msg_type (void) const; + void msg_type (ACE_UINT32); + + // = Set/get the time + const ACE_UINT32 time (void) const; + void time (const ACE_UINT32 t); + + // = Set/get the blocking semantics. + ACE_UINT32 block_forever (void) const; + void block_forever (ACE_UINT32); + + // = Set/get the timeout. + ACE_Time_Value timeout (void) const; + void timeout (const ACE_Time_Value timeout); + + int encode (void *&); + // Encode the message before transmission. + + int decode (void); + // Decode message after reception. + + void dump (void) const; + // Print out the values of the message for debugging purposes. + +private: + // = The 5 fields in the <Transfer> struct are transmitted to the server. + // The remaining 2 fields are not tranferred -- they are used only on + // the server-side to simplify lookups. + + struct Transfer + { + ACE_UINT32 msg_type_; + // Type of the request (i.e., <TIME_UPDATE>) + + ACE_UINT32 block_forever_; + // Indicates if we should block forever. If 0, then <secTimeout_> + // and <usecTimeout_> indicates how long we should wait. + + ACE_UINT32 sec_timeout_; + // Max seconds willing to wait for name if not blocking forever. + + ACE_UINT32 usec_timeout_; + // Max micro seconds to wait for name if not blocking forever. + + ACE_UINT32 time_; + // The data portion contains <time_> + }; + + Transfer transfer_; + // Transfer buffer. + + ACE_UINT32 time_; + // Time +}; + + +#endif /* ACE_TIME_REQUEST_REPLY_H */ diff --git a/ace/Time_Value.cpp b/ace/Time_Value.cpp new file mode 100644 index 00000000000..c6aef0b8fa4 --- /dev/null +++ b/ace/Time_Value.cpp @@ -0,0 +1,231 @@ +// Time_Value.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/ACE.h" +#include "ace/Time_Value.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Time_Value.i" +#endif /* __ACE_INLINE__ */ + +// Static constant representing `zero-time'. +const ACE_Time_Value ACE_Time_Value::zero; + +ACE_ALLOC_HOOK_DEFINE(ACE_Time_Value) + +/* Initializes the ACE_Time_Value object from a timeval. */ + +ACE_Time_Value::ACE_Time_Value (const timeval &tv) +{ + ACE_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (tv); +} + +#if defined(ACE_WIN32) +// Initializes the ACE_Time_Value object from a Win32 FILETIME + +ACE_Time_Value::ACE_Time_Value (const FILETIME &file_time) +{ + ACE_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 + ACE_QWORD _100ns = ACE_MAKE_QWORD (file_time.dwLowDateTime, + file_time.dwHighDateTime); + // Convert 100ns units to seconds; + this->tv_sec_ = long (_100ns / (10000 * 1000)); + // Convert remainder to microseconds; + this->tv_usec_ = long ((_100ns - (this->tv_sec_ * (10000 * 1000))) / 10); +} + +// Returns the value of the object as a Win32 FILETIME. + +ACE_Time_Value::operator FILETIME () const +{ + ACE_TRACE ("ACE_Time_Value::operator FILETIME"); + ACE_QWORD _100ns = ((ACE_QWORD) this->tv_sec_ * (1000 * 1000) + this->tv_usec_) * 10; + FILETIME file_time; + file_time.dwLowDateTime = ACE_LOW_DWORD (_100ns); + file_time.dwHighDateTime = ACE_HIGH_DWORD (_100ns); + return file_time; +} + +#endif + +void +ACE_Time_Value::dump (void) const +{ + ACE_TRACE ("ACE_Time_Value::dump"); +#if 0 + if (tv.usec () < 0 || tv.sec () < 0) + stream << "-"; + + stream << dec << abs (int (tv.sec ())) << "." +// << setw (6) << setfill ('0') + << dec << abs (int (tv.usec ())); +// I assume + inline int abs(int d) { return (d>0)?d:-d; } + is defined somewhere */ +#endif /* 0 */ +} + +void +ACE_Time_Value::set (long sec, long usec) +{ + ACE_TRACE ("ACE_Time_Value::set"); + this->tv_sec_ = sec; + this->tv_usec_ = usec; +} + +ACE_Time_Value::ACE_Time_Value (long sec, long usec) +{ + ACE_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (sec, usec); + this->normalize (); +} + +// Returns the value of the object as a timeval. + +ACE_Time_Value::operator timeval () const +{ + ACE_TRACE ("ACE_Time_Value::operator timeval"); + timeval tv; + tv.tv_sec = this->tv_sec_; + tv.tv_usec = this->tv_usec_; + return tv; +} + +// Add TV to this. + +void +ACE_Time_Value::operator+= (const ACE_Time_Value &tv) +{ + ACE_TRACE ("ACE_Time_Value::operator+="); + this->tv_sec_ += tv.tv_sec_; + this->tv_usec_ += tv.tv_usec_; + this->normalize (); +} + +// Subtract TV to this. + +void +ACE_Time_Value::operator-= (const ACE_Time_Value &tv) +{ + ACE_TRACE ("ACE_Time_Value::operator-="); + this->tv_sec_ -= tv.tv_sec_; + this->tv_usec_ -= tv.tv_usec_; + this->normalize (); +} + +// Adds two ACE_Time_Value objects together, returns the sum. + +ACE_Time_Value +operator + (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator +"); + ACE_Time_Value sum (tv1.tv_sec_ + tv2.tv_sec_, + tv1.tv_usec_ + tv2.tv_usec_); + + sum.normalize (); + return sum; +} + +// Subtracts two ACE_Time_Value objects, returns the difference. + +ACE_Time_Value +operator - (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator -"); + ACE_Time_Value delta (tv1.tv_sec_ - tv2.tv_sec_, + tv1.tv_usec_ - tv2.tv_usec_); + delta.normalize (); + return delta; +} + +// True if tv1 > tv2. + +int +operator > (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator >"); + if (tv1.tv_sec_ > tv2.tv_sec_) + return 1; + else if (tv1.tv_sec_ == tv2.tv_sec_ + && tv1.tv_usec_ > tv2.tv_usec_) + return 1; + else + return 0; +} + +// True if tv1 >= tv2. + +int +operator >= (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator >="); + if (tv1.tv_sec_ > tv2.tv_sec_) + return 1; + else if (tv1.tv_sec_ == tv2.tv_sec_ + && tv1.tv_usec_ >= tv2.tv_usec_) + return 1; + else + return 0; +} + +void +ACE_Time_Value::normalize (void) +{ + ACE_TRACE ("ACE_Time_Value::normalize"); + // New code from Hans Rohnert... + + if (this->tv_usec_ >= ONE_SECOND) + { + do + { + this->tv_sec_++; + this->tv_usec_ -= ONE_SECOND; + } + while (this->tv_usec_ >= ONE_SECOND); + } + else if (this->tv_usec_ <= -ONE_SECOND) + { + do + { + this->tv_sec_--; + this->tv_usec_ += ONE_SECOND; + } + while (this->tv_usec_ <= -ONE_SECOND); + } + + if (this->tv_sec_ >= 1 && this->tv_usec_ < 0) + { + this->tv_sec_--; + this->tv_usec_ += ONE_SECOND; + } + else if (this->tv_sec_ < 0 && this->tv_usec_ > 0) + { + this->tv_sec_++; + this->tv_usec_ -= ONE_SECOND; + } + +#if 0 + // Old code... + while ((this->tv_usec_ >= ONE_SECOND) + || (this->tv_sec_ < 0 && this->tv_usec_ > 0 )) + { + this->tv_usec_ -= ONE_SECOND; + this->tv_sec_++; + } + + while ((this->tv_usec_ <= -ONE_SECOND) + || (this->tv_sec_ > 0 && this->tv_usec_ < 0)) + { + this->tv_usec_ += ONE_SECOND; + this->tv_sec_--; + } +#endif +} diff --git a/ace/Time_Value.h b/ace/Time_Value.h new file mode 100644 index 00000000000..900c169eff6 --- /dev/null +++ b/ace/Time_Value.h @@ -0,0 +1,247 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Time_Value.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TIME_VALUE_H) +#define ACE_TIME_VALUE_H + +// This file should be a link to the platform/compiler-specific +// configuration file (e.g., config-sunos5-sunc++-4.x.h). By +// including this here we avoid nasty circular include problems... +#include "ace/config.h" + +#if defined (__ACE_INLINE__) +#define ACE_INLINE inline +#else +#define ACE_INLINE +#endif /* __ACE_INLINE__ */ + +// Nasty macro stuff to account for Microsoft Win32 DLL nonsense. We +// use these macros so that we don't end up with ACE software +// hard-coded to Microsoft proprietary extensions to C++. + +#if defined (ACE_HAS_DLL) +#if defined (ACE_BUILD_DLL) +#if !defined (_MSC_VER) /* Mark classes as exported, Borland. */ +#define ACE_Export _export +#else /* Microsoft: */ +#define ACE_Export __declspec (dllexport) +#endif /* !_MSC_VER */ +#else /* Using the DLL. */ +#if !defined _MSC_VER +#define ACE_Export _import +#else +#define ACE_Export __declspec (dllimport) +#endif /* !_MSC_VER */ +#endif /* ACE_BUILD_DLL */ + +#else /* We're not building a DLL! */ +#define ACE_Export +#endif /* ACE_HAS_DLL */ + +#if defined (ACE_HAS_DLL) +#if defined (ACE_BUILD_SVC_DLL) +#if !defined (_MSC_VER) /* Mark classes as exported, Borland. */ +#define ACE_Svc_Export _export +#else /* Microsoft: */ +#define ACE_Svc_Export __declspec (dllexport) +#endif /* !_MSC_VER */ +#else /* Using the DLL. */ +#if !defined _MSC_VER +#define ACE_Svc_Export _import +#else +#define ACE_Svc_Export __declspec (dllimport) +#endif /* !_MSC_VER */ +#endif /* ACE_BUILD_DLL || ACE_BUILD_SVC_DLL */ + +#else /* We're not building a DLL! */ +#define ACE_Svc_Export +#endif /* ACE_HAS_DLL */ + +// This needs to go here *first* to avoid problems with AIX. +// Just to be safe we'll do it with pthreads, too -- jwr +#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) +extern "C" { +#include <pthread.h> +} +#endif /* ACE_HAS_DCETHREADS */ + +#if (ACE_NTRACE == 1) +#define ACE_TRACE(X) +#else +#define ACE_TRACE(X) ACE_Trace ____ (X, __LINE__, __FILE__) +#endif /* ACE_NTRACE */ + +#include <time.h> +#if defined (ACE_NEEDS_SYSTIME_H) +// Some platforms may need to include this, but I suspect that most +// will get it from <time.h> +#if defined (VXWORKS) +#include <sys/times.h> +#else +#include <sys/time.h> +#endif /* VXWORKS */ +#endif /* ACE_NEEDS_SYSTIME_H */ + +#if !defined (ACE_HAS_POSIX_TIME) +// 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 <sys/timers.h> - Tom Marrs +#include <sys/timers.h> +#endif /* ACE_HAS_POSIX_TIME */ + +#if !defined (ACE_HAS_SVR4_TIME) +// Definition per SVr4. +typedef struct timespec timestruc_t; +#endif /* ACE_HAS_SVR4_TIME */ + +class ACE_Export ACE_Time_Value + // = TITLE + // Operations on "timeval" structures. + // + // = DESCRIPTION + // This class centralizes all the time-related processing in + // ACE. These timers are typically used in conjunction with + // lower-level OS mechanisms like select(), poll(), or + // cond_timedwait(). ACE_Time_Value help make the use of these + // mechanisms portable across OS platforms, +{ +public: + // = Useful constants. + static const ACE_Time_Value zero; + // Constant "0". + + // = Initialization method. + ACE_Time_Value (long sec = 0, long usec = 0); + // Default constructor. + + // = Methods for converting to/from various time formats. + ACE_Time_Value (const struct timeval &t); + // Construct a Time_Value from a timeval. + + ACE_Time_Value (const timestruc_t &t); + // Initializes the ACE_Time_Value object from a timestruc_t. + + ACE_Time_Value (const ACE_Time_Value &tv); + // Copy constructor. + +#if defined(ACE_WIN32) + ACE_Time_Value (const FILETIME &ft); + // Initializes the ACE_Time_Value object from a Win32 FILETIME +#endif + + void set (long sec = 0, long usec = 0); + // Construct a Time_Value from a timeval. + + void set (const timeval &t); + // Construct a Time_Value from a timeval. + + void set (const timestruc_t &t); + // Initializes the ACE_Time_Value object from a timestruc_t. + +#if defined(ACE_WIN32) + void set (const FILETIME &ft); + // Initializes the ACE_Time_Value object from a timestruc_t. +#endif + + long msec (void) const; + // Converts from Time_Value format into milli-seconds format. + + void msec (long); + // Converts from milli-seconds format into Time_Value format. + + operator timestruc_t () const; + // Returns the value of the object as a timestruc_t. + + operator timeval () const; + // Returns the value of the object as a timeval. + +#if defined(ACE_WIN32) + operator FILETIME () const; + // Returns the value of the object as a Win32 FILETIME. +#endif + + // = The following are accessor/mutator methods. + + long sec (void) const; + // Get seconds. + + void sec (long sec); + // Set seconds. + + long usec (void) const; + // Get microseconds. + + void usec (long usec); + // Set microseconds. + + // = The following are arithmetic methods for operating on + // Time_Values. + + void operator += (const ACE_Time_Value &tv); + // Add <tv> to this. + + void operator -= (const ACE_Time_Value &tv); + // Subtract <tv> to this. + + friend ACE_Export ACE_Time_Value operator + (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // Adds two ACE_Time_Value objects together, returns the sum. + + friend ACE_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_Export int operator < (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // True if tv1 < tv2. + + friend ACE_Export int operator > (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // True if tv1 > tv2. + + friend ACE_Export int operator <= (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // True if tv1 <= tv2. + + friend ACE_Export int operator >= (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // True if tv1 >= tv2. + + friend ACE_Export int operator == (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // True if tv1 == tv2. + + friend ACE_Export int operator != (const ACE_Time_Value &tv1, const ACE_Time_Value &tv2); + // True if tv1 != tv2. + + void dump (void) const; + // Dump the state of an object. + +private: + void normalize (void); + // Put the timevalue into a canonical form. + + long tv_sec_; + // Seconds. + + long tv_usec_; + // Microseconds. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Time_Value.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_TIME_VALUE */ diff --git a/ace/Time_Value.i b/ace/Time_Value.i new file mode 100644 index 00000000000..9d88167b1c0 --- /dev/null +++ b/ace/Time_Value.i @@ -0,0 +1,166 @@ +/* -*- C++ -*- */ +// $Id$ + +// Time_Value.i + +#include "ace/Trace.h" + +// Don't put this in the class since it will expand the size! Also, +// can't make this an enum due to compiler bugs on some platforms... +static const long ONE_SECOND = 1000000L; + +// Initializes the ACE_Time_Value object. + +// Initializes a timestruc_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 +// anyway?! + +ACE_INLINE void +ACE_Time_Value::set (const timestruc_t &tv) +{ + ACE_TRACE ("ACE_Time_Value::set"); + this->tv_sec_ = tv.tv_sec; + this->tv_usec_ = tv.tv_nsec / 1000; + + this->normalize (); +} + +// Returns the value of the object as a timestruc_t. + +ACE_INLINE +ACE_Time_Value::operator timestruc_t () const +{ + ACE_TRACE ("ACE_Time_Value::operator timestruc_t"); + timestruc_t tv; + tv.tv_sec = this->tv_sec_; + tv.tv_nsec = this->tv_usec_ * 1000; + return tv; +} + +// Initializes the ACE_Time_Value object from a timestruc_t. + +ACE_INLINE +ACE_Time_Value::ACE_Time_Value (const timestruc_t &tv) +{ + ACE_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (tv); +} + +ACE_INLINE void +ACE_Time_Value::set (const timeval &tv) +{ + ACE_TRACE ("ACE_Time_Value::set"); + this->tv_sec_ = tv.tv_sec; + this->tv_usec_ = tv.tv_usec; + + this->normalize (); +} + +// 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_sec_ (tv.tv_sec_), + tv_usec_ (tv.tv_usec_) +{ + ACE_TRACE ("ACE_Time_Value::ACE_Time_Value"); +} + +// Returns number of seconds. + +ACE_INLINE long +ACE_Time_Value::sec (void) const +{ + ACE_TRACE ("ACE_Time_Value::sec"); + return this->tv_sec_; +} + +// Sets the number of seconds. + +ACE_INLINE void +ACE_Time_Value::sec (long sec) +{ + ACE_TRACE ("ACE_Time_Value::sec"); + this->tv_sec_ = sec; +} + +// Converts from Time_Value format into milli-seconds format. + +ACE_INLINE long +ACE_Time_Value::msec (void) const +{ + ACE_TRACE ("ACE_Time_Value::msec"); + return this->tv_sec_ * 1000 + this->tv_usec_ / 1000; +} + +// Converts from milli-seconds format into Time_Value format. + +ACE_INLINE void +ACE_Time_Value::msec (long milliseconds) +{ + ACE_TRACE ("ACE_Time_Value::msec"); + // Convert millisecond units to seconds; + this->tv_sec_ = milliseconds / 1000; + // Convert remainder to microseconds; + this->tv_usec_ = (milliseconds - (this->tv_sec_ * 1000)) * 1000; +} + +// Returns number of micro-seconds. + +ACE_INLINE long +ACE_Time_Value::usec (void) const +{ + ACE_TRACE ("ACE_Time_Value::usec"); + return this->tv_usec_; +} + +// Sets the number of micro-seconds. + +ACE_INLINE void +ACE_Time_Value::usec (long usec) +{ + ACE_TRACE ("ACE_Time_Value::usec"); + this->tv_usec_ = usec; +} + +// True if tv1 < tv2. + +ACE_INLINE int +operator < (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator <"); + return tv2 > tv1; +} + +// True if tv1 >= tv2. + +ACE_INLINE int +operator <= (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator <="); + return tv2 >= tv1; +} + +// True if tv1 == tv2. + +ACE_INLINE int +operator == (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator =="); + return tv1.tv_sec_ == tv2.tv_sec_ + && tv1.tv_usec_ == tv2.tv_usec_; +} + +// True if tv1 != tv2. + +ACE_INLINE int +operator != (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_TRACE ("operator !="); + return !(tv1 == tv2); +} diff --git a/ace/Timer_Queue.cpp b/ace/Timer_Queue.cpp new file mode 100644 index 00000000000..9a26fb4bbf0 --- /dev/null +++ b/ace/Timer_Queue.cpp @@ -0,0 +1,332 @@ +// Timer_Queue.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Timer_Queue.h" + +ACE_ALLOC_HOOK_DEFINE(ACE_Timer_Node) + +void +ACE_Timer_Node::dump (void) const +{ + ACE_TRACE ("ACE_Timer_Node::dump"); +} + +ACE_Timer_Node::ACE_Timer_Node (ACE_Event_Handler *h, + const void *a, + const ACE_Time_Value &t, + const ACE_Time_Value &i, + ACE_Timer_Node *n, + int timer_id) + : handler_ (h), + arg_ (a), + timer_value_ (t), + interval_ (i), + next_ (n), + timer_id_ (timer_id) +{ + ACE_TRACE ("ACE_Timer_Node::ACE_Timer_Node"); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Timer_Queue) + +void +ACE_Timer_Queue::dump (void) const +{ + ACE_TRACE ("ACE_Timer_Queue::dump"); +} + +// Create an empty queue. + +ACE_Timer_Queue::ACE_Timer_Queue (void) + : head_ (0), + timer_id_ (0) +{ + ACE_TRACE ("ACE_Timer_Queue::ACE_Timer_Queue"); +} + +// Checks if queue is empty. + +int +ACE_Timer_Queue::is_empty (void) const +{ + ACE_TRACE ("ACE_Timer_Queue::is_empty"); + return this->head_ == 0; +} + +// Returns earliest time in a non-empty queue. + +const ACE_Time_Value & +ACE_Timer_Queue::earliest_time (void) const +{ + ACE_TRACE ("ACE_Timer_Queue::earliest_time"); + return this->head_->timer_value_; +} + +// Remove all remaining items in the queue. + +ACE_Timer_Queue::~ACE_Timer_Queue (void) +{ + ACE_TRACE ("ACE_Timer_Queue::~ACE_Timer_Queue"); + ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_)); + + ACE_Timer_Node *curr = this->head_; + + while (curr != 0) + { + ACE_Timer_Node *next = curr->next_; + delete curr; + curr = next; + } +} + +// Reschedule a periodic timer. This function must be called with the +// mutex lock held. + +void +ACE_Timer_Queue::reschedule (ACE_Timer_Node *expired) +{ + ACE_TRACE ("ACE_Timer_Queue::reschedule"); + if (this->is_empty () || expired->timer_value_ < this->earliest_time ()) + { + expired->next_ = this->head_; + this->head_ = expired; + } + else + { + ACE_Timer_Node *prev = this->head_; + ACE_Timer_Node *after = this->head_->next_; + + // Locate the proper position in the queue. + + while (after != 0 + && expired->timer_value_ > after->timer_value_) + { + prev = after; + after = after->next_; + } + + expired->next_ = after; + prev->next_ = expired; + } +} + +// Insert a new handler that expires at time future_time; if interval +// is > 0, the handler will be reinvoked periodically. + +int +ACE_Timer_Queue::schedule (ACE_Event_Handler *handler, + const void *arg, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval) +{ + ACE_TRACE ("ACE_Timer_Queue::schedule"); + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1)); + + // Increment the sequence number (it will wrap around). + this->timer_id_++; + + if (this->is_empty () || future_time < this->earliest_time ()) + { + // Place at the beginning of the list. + ACE_NEW_RETURN (this->head_, + ACE_Timer_Node (handler, + arg, + future_time, + interval, + this->head_, + this->timer_id_), + -1); + return this->head_ ? this->timer_id_ : -1; + } + else // Place in the middle of the list somewhere. + { + ACE_Timer_Node *prev = this->head_; + ACE_Timer_Node *after = this->head_->next_; + + while (after != 0 && future_time > after->timer_value_) + { + prev = after; + after = after->next_; + } + + ACE_NEW_RETURN (prev->next_, + ACE_Timer_Node (handler, + arg, + future_time, + interval, + after, + this->timer_id_), + -1); + return prev->next_ ? this->timer_id_ : -1; + } +} + +// Locate and remove the single <ACE_Event_Handler> with a value of +// <timer_id> from the timer queue. + +int +ACE_Timer_Queue::cancel (int timer_id, const void **arg) +{ + ACE_TRACE ("ACE_Timer_Queue::cancel"); + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1)); + + ACE_Timer_Node *prev = 0; + ACE_Timer_Node *curr = 0; + + // Try to locate the ACE_Timer_Node that matches the timer_id. + + for (curr = this->head_; + curr != 0 && curr->timer_id_ != timer_id; + curr = curr->next_) + prev = curr; + + if (curr != 0) + { + if (prev == 0) + this->head_ = curr->next_; + else + prev->next_ = curr->next_; + + if (arg != 0) + *arg = curr->arg_; + + delete curr; + return 0; + } + else + return -1; +} + +// Locate and remove all values of <handler> from the timer queue. + +int +ACE_Timer_Queue::cancel (ACE_Event_Handler *handler) +{ + ACE_TRACE ("ACE_Timer_Queue::cancel"); + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1)); + + ACE_Timer_Node *prev = 0; + ACE_Timer_Node *curr = this->head_; + + while (curr != 0) + { + if (curr->handler_ == handler) + { + if (prev == 0) + { + this->head_ = curr->next_; + delete curr; + curr = this->head_; + } + else + { + prev->next_ = curr->next_; + delete curr; + curr = prev->next_; + } + } + else + { + prev = curr; + curr = curr->next_; + } + } + + return 0; +} + +// Run the <handle_timeout> method for all Timers whose values are <= +// <cur_time>. + +int +ACE_Timer_Queue::expire (const ACE_Time_Value &cur_time) +{ + ACE_TRACE ("ACE_Timer_Queue::expire"); + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1)); + + for (;;) + { + if (this->is_empty () || this->earliest_time () > cur_time) + break; // There aren't any more timers eligible to expire. + + ACE_Timer_Node *expired = this->head_; + ACE_Event_Handler *handler = + (ACE_Event_Handler *) expired->handler_; + const void *arg = expired->arg_; + int reclaim = 1; + int result; + + this->head_ = this->head_->next_; + + // Check whether this is an interval timer. + if (expired->interval_ > ACE_Time_Value::zero) + { + // Make sure that we skip past values that have already + // "expired". + do + expired->timer_value_ += expired->interval_; + while (expired->timer_value_ <= cur_time); + + // Since this is an interval timer, we need to reschedule + // it. + this->reschedule (expired); + reclaim = 0; + } + + // Perform the callback. + result = handler->handle_timeout (cur_time, arg); + + if (result == -1) + this->cancel (handler); + + if (reclaim) + delete expired; + } + return 0; +} + +// Determines the maximum amount of time that the Reactor must wait +// before timing out. This is computed as the smaller of (1) the +// amount the caller requested when calling handle_events() and (2) +// the earliest time registered in the Timer Queue (if any). Must be +// called with locks held since it returns a pointer to a Time_Value +// object stored in the Timer_Queue object itself. If the lock isn't +// held we'll have reentrancy problems!) + +ACE_Time_Value * +ACE_Timer_Queue::calculate_timeout (ACE_Time_Value *max_wait_time) +{ + ACE_TRACE ("ACE_Timer_Queue::calculate_timeout"); + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, max_wait_time)); + + if (this->is_empty ()) + // Nothing on the Timer_Queue, so use whatever the caller gave us. + return max_wait_time; + else + { + ACE_Time_Value cur_time = ACE_OS::gettimeofday (); + + if (this->earliest_time () > cur_time) + { + // The earliest item on the Timer_Queue is still in the + // future. Therefore, use the smaller of (1) caller's wait + // time or (2) the delta time between now and the earliest + // time on the Timer_Queue. + + this->timeout_ = this->earliest_time () - cur_time; + if (max_wait_time == 0 || *max_wait_time > timeout_) + return &this->timeout_; + else + return max_wait_time; + } + else + { + // The earliest item on the Timer_Queue is now in the past. + // Therefore, we've got to "poll" the Reactor, i.e., it must + // just check the descriptors and then dispatch timers, etc. + this->timeout_ = ACE_Time_Value::zero; + return &this->timeout_; + } + } +} diff --git a/ace/Timer_Queue.h b/ace/Timer_Queue.h new file mode 100644 index 00000000000..90972f34598 --- /dev/null +++ b/ace/Timer_Queue.h @@ -0,0 +1,154 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Timer_Queue.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TIMER_QUEUE_H) +#define ACE_TIMER_QUEUE_H + +#include "ace/Event_Handler.h" +#include "ace/Time_Value.h" +#include "ace/Synch.h" + +// This should be nested within the ACE_Timer_Queue class but some C++ +// compilers still don't like this... + +struct ACE_Timer_Node + // = TITLE + // Maintains the state associated with a Timer entry. +{ +friend class ACE_Timer_Queue; +private: + ACE_Timer_Node (ACE_Event_Handler *h, + const void *a, + const ACE_Time_Value &t, + const ACE_Time_Value &i, + ACE_Timer_Node *n, + int timer_id); + // Constructor. + + ACE_Event_Handler *handler_; + // Handler to invoke <handle_timeout> on when a timeout occurs. + + const void *arg_; + // Argument to pass to <handle_timeout>. + + ACE_Time_Value timer_value_; + // Time until the timer expires. + + ACE_Time_Value interval_; + // If this is a periodic timer this holds the time until the next + // timeout. + + ACE_Timer_Node *next_; + // Pointer to next timer. + + int timer_id_; + // Id of this timer (used to cancel timers before they expire). + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + void dump (void) const; + // Dump the state of an object. +}; + +class ACE_Export ACE_Timer_Queue + // = TITLE + // Provides an interface to timers. + // + // = DESCRIPTION + // This is a simple implementation that uses a linked list of + // absolute times. A more clever implementation would use a + // delta-list, a heap, or timing wheels, etc. +{ +public: + // = Initialization and termination methods. + ACE_Timer_Queue (void); + // Default constructor. + virtual ~ACE_Timer_Queue (void); + + int is_empty (void) const; + // True if queue is empty, else false. + + const ACE_Time_Value &earliest_time (void) const; + // Returns the time of the earlier node in the Timer_Queue. + + virtual int schedule (ACE_Event_Handler *event_handler, + const void *arg, + const ACE_Time_Value &delay, + const ACE_Time_Value &interval = ACE_Time_Value::zero); + // Schedule an <event_handler> that will expire after <delay> amount + // of time. If it expires then <arg> is passed in as the value to + // the <event_handler>'s <handle_timeout> callback method. If + // <interval> is != to <ACE_Time_Value::zero> then it is used to + // reschedule the <event_handler> automatically. This method + // returns a timer handle that uniquely identifies the + // <event_handler> in an internal list. This timer handle can be + // used to cancel an <event_handler> before it expires. The + // cancellation ensures that timer_ids are unique up to values of + // greater than 2 billion timers. As long as timers don't stay + // around longer than this there should be no problems with + // accidentally deleting the wrong timer. + + virtual int cancel (ACE_Event_Handler *event_handler); + // Cancel all <event_handlers> that match the address of + // <event_handler>. + + virtual int cancel (int timer_id, const void **arg = 0); + // Cancel the single <ACE_Event_Handler> that matches the <timer_id> + // value (which was returned from the <schedule> method). If arg is + // non-NULL then it will be set to point to the ``magic cookie'' + // argument passed in when the <Event_Handler> was registered. This + // makes it possible to free up the memory and avoid memory leaks. + + virtual int expire (const ACE_Time_Value ¤t_time); + // Run the <handle_timeout> method for all Timers whose values are + // <= <cur_time>. + + virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max); + // Determine the next event to timeout. Returns <max> if there are + // no pending timers or if all pending timers are longer than max. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Time_Value timeout_; + // Returned by calculate_timeout. + + virtual void reschedule (ACE_Timer_Node *); + // Reschedule a "period" Timer_Node. + + ACE_Timer_Node *head_; + // Pointer to linked list of ACE_Timer_Handles. + + int timer_id_; + // Keeps track of the timer id that uniquely identifies each timer. + // This id can be used to cancel a timer via the <cancel (int)> + // method. + +#if defined (ACE_MT_SAFE) + ACE_Recursive_Thread_Mutex lock_; + // Synchronization variable for the MT_SAFE ACE_Reactor +#endif /* ACE_MT_SAFE */ +}; + +#include "ace/Timer_Queue.i" + +#endif /* ACE_TIMER_QUEUE_H */ diff --git a/ace/Timer_Queue.i b/ace/Timer_Queue.i new file mode 100644 index 00000000000..f2733b140a4 --- /dev/null +++ b/ace/Timer_Queue.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Timer_Queue.i diff --git a/ace/Token.cpp b/ace/Token.cpp new file mode 100644 index 00000000000..30cf2943169 --- /dev/null +++ b/ace/Token.cpp @@ -0,0 +1,346 @@ +// Token.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Thread.h" +#include "ace/Time_Value.h" +#include "ace/Token.h" + +#if defined (ACE_HAS_THREADS) + +#if !defined (__ACE_INLINE__) +#include "ace/Token.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Token) + +void +ACE_Token::dump (void) const +{ + ACE_TRACE ("ACE_Token::dump"); +} + +ACE_Token::ACE_Queue_Entry::ACE_Queue_Entry (ACE_Thread_Mutex &m, + ACE_thread_t t_id) + : cv_ (m), + next_ (0), + thread_id_ (t_id), + runable_ (0) +{ + ACE_TRACE ("ACE_Token::ACE_Queue_Entry::ACE_Queue_Entry"); +} + +ACE_Token::ACE_Token (const char *name, void *any) + : head_ (0), + tail_ (0), + lock_ (name, any), + in_use_ (0), + waiters_ (0), + nesting_level_ (0) +{ +// ACE_TRACE ("ACE_Token::ACE_Token"); +} + +ACE_Token::~ACE_Token (void) +{ + ACE_TRACE ("ACE_Token::~ACE_Token"); +} + +// Remove an entry from the list. Must be +// called with locks held. + +void +ACE_Token::remove_entry (ACE_Token::ACE_Queue_Entry *entry) +{ + ACE_TRACE ("ACE_Token::remove_entry"); + ACE_Token::ACE_Queue_Entry *curr = 0; + ACE_Token::ACE_Queue_Entry *prev = 0; + + if (this->head_ == 0) + return; + + for (curr = this->head_; + curr != 0 && curr != entry; + curr = curr->next_) + prev = curr; + + if (curr == 0) // Didn't find the entry... + return; + else if (prev == 0) // Delete at the head. + this->head_ = this->head_->next_; + else // Delete in the middle. + prev->next_ = curr->next_; + + // We need to update the tail of the list + // if we've deleted the last entry. + + if (curr->next_ == 0) + this->tail_ = curr; +} + +int +ACE_Token::shared_acquire (void (*sleep_hook_func)(void *), + void *arg, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_Token::shared_acquire"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + ACE_thread_t thr_id = ACE_Thread::self (); + +#if defined (DEBUGGING) + cerr << '(' << ACE_Thread::self () << ')' + << " acquire: owner_ = " << this->owner_ + << ", owner_ addr = " << &this->owner_ + << ", nesting level = " << this->nesting_level_ << endl; +#endif /* DEBUGGING */ + + if (this->in_use_) // Someone already holds the token. + { + if (ACE_OS::thr_equal (thr_id, this->owner_)) // I own it! + { + this->nesting_level_++; + return 0; + } + // Do a quick check for "polling" behavior. + else if (timeout != 0 && timeout->sec () == 0 && timeout->usec () == 0) + { + errno = ETIME; + return -1; + } + else // We've got to sleep until we get the token. + { + // Allocate q entry on stack. This works since we don't + // exit this method's activation record until we've got the + // token. + ACE_Token::ACE_Queue_Entry my_entry (this->lock_, thr_id); + int ret = 0; + + if (this->head_ == 0) // I'm first and only waiter in line... + { + this->head_ = &my_entry; + this->tail_ = &my_entry; + } + else // I'm queued at the end of the list. + { + this->tail_->next_ = &my_entry; + this->tail_ = &my_entry; + } + + this->waiters_++; + + // Execute appropriate <sleep_hook> callback. + // (@@ should these methods return a success/failure + // status, and if so, what should we do with it?) + + if (sleep_hook_func) + { + (*sleep_hook_func) (arg); + ret++; + } + else // Execute virtual method. + { + this->sleep_hook (); + ret++; + } + + // Sleep until we've got the token (ignore signals). + + while (my_entry.cv_.wait (timeout) == -1) + { + // Note, this should obey whatever thread-specific + // interrupt policy is currently in place... + if (errno == EINTR) + continue; +#if defined (DEBUGGING) + cerr << '(' << ACE_Thread::self () << ')' + << " acquire: " + << (errno == ETIME ? "timed out" : "error occurred") + << endl; +#endif /* DEBUGGING */ + // We come here if a timeout occurs or some serious + // ACE_Condition object error. + this->remove_entry (&my_entry); + return -1; + } + + ACE_ASSERT (my_entry.runable_); +#if defined (DEBUGGING) + cerr << '(' << ACE_Thread::self () << ')' + << " acquire (UNBLOCKED)" << endl; +#endif /* DEBUGGING */ + return ret; + } + } + else + { + this->in_use_ = 1; + this->owner_ = thr_id; // Its mine! + return 0; + } +} + +// By default this is a no-op. + +/* virtual */ +void +ACE_Token::sleep_hook (void) +{ + ACE_TRACE ("ACE_Token::sleep_hook"); +} + +int +ACE_Token::acquire (ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_Token::acquire"); + return this->shared_acquire (0, 0, timeout); +} + +// Acquire the token, sleeping until it is obtained or until +// <timeout> expires. + +int +ACE_Token::acquire (void (*sleep_hook_func)(void *), + void *arg, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_Token::acquire"); + return this->shared_acquire (sleep_hook_func, arg, timeout); +} + +// Try to renew the token. + +int +ACE_Token::renew (int requeue_position, ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_Token::renew"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + +#if defined (DEBUGGING) + cerr << '(' << ACE_Thread::self () << ')' + << " renew: owner_ thr = " << this->owner_ + << ", owner_ addr = " << &this->owner_ + << ", nesting level = " << this->nesting_level_ << endl; +#endif /* DEBUGGING */ + ACE_ASSERT (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_)); + + // Check to see if there are any waiters. If not, we just keep the token. + if (this->head_ != 0) + { + ACE_Token::ACE_Queue_Entry my_entry (this->lock_, this->owner_); + int save_nesting_level_ = this->nesting_level_; + + this->owner_ = this->head_->thread_id_; + this->nesting_level_ = 0; + + // Wake up next waiter and make it runable. + this->head_->cv_.signal (); + this->head_->runable_ = 1; + + this->head_ = this->head_->next_; + + if (this->head_ == 0) // No other threads - just add me + { + this->head_ = &my_entry; + this->tail_ = &my_entry; + } + else if (requeue_position == -1) // Insert at the end of the queue. + { + this->tail_->next_ = &my_entry; + this->tail_ = &my_entry; + } + else if (requeue_position == 0) // Insert at head of queue. + { + my_entry.next_ = this->head_; + this->head_ = &my_entry; + } + else // Insert in the middle of the queue somewhere. + { + ACE_Token::ACE_Queue_Entry *insert_after = this->head_; + + // Determine where our thread should go in the queue of + // waiters. + + while (requeue_position-- && insert_after->next_ != 0) + insert_after = insert_after->next_; + + my_entry.next_ = insert_after->next_; + + if (my_entry.next_ == 0) + this->tail_ = &my_entry; + + insert_after->next_ = &my_entry; + } + + // Sleep until we've got the token (ignore signals). + + while (my_entry.cv_.wait (timeout) == -1) + { + // Note, this should obey whatever thread-specific + // interrupt policy is currently in place... + if (errno == EINTR) + continue; +#if defined (DEBUGGING) + cerr << '(' << ACE_Thread::self () << ')' + << " renew: " + << (errno == ETIME ? "timed out" : "error occurred") << endl; +#endif /* DEBUGGING */ + // We come here if a timeout occurs or + // some serious ACE_Condition object error. + this->remove_entry (&my_entry); + return -1; + } + + ACE_ASSERT (my_entry.runable_); + this->nesting_level_ = save_nesting_level_; + this->owner_ = my_entry.thread_id_; + } + return 0; +} + +// Release the current holder of the token (which had +// better be the caller's thread!). + +int +ACE_Token::release (void) +{ + ACE_TRACE ("ACE_Token::release"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + ACE_ASSERT (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_)); + +#if defined (DEBUGGING) + cerr << '(' << ACE_Thread::self () << ')' + << " release: owner_ thr = " << this->owner_ + << ", owner_ addr = " << &this->owner_ + << ", nesting level = " << this->nesting_level_ << endl; +#endif /* DEBUGGING */ + + if (this->nesting_level_ > 0) + --this->nesting_level_; + else + { + if (this->head_ == 0) + this->in_use_ = 0; // No more waiters... + else + { + this->owner_ = this->head_->thread_id_; + --this->waiters_; + + // Wake up waiter and make it runable. + this->head_->cv_.signal (); + this->head_->runable_ = 1; + + this->head_ = this->head_->next_; + + if (this->head_ == 0) + this->tail_ = 0; + } + } + return 0; +} + +#endif /* ACE_HAS_THREADS */ + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Token.h b/ace/Token.h new file mode 100644 index 00000000000..a29d3f95d43 --- /dev/null +++ b/ace/Token.h @@ -0,0 +1,173 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Token.h +// +// = AUTHOR +// Original author -- Karl-Heinz Dorn (kdorn@erlh.siemens.de) +// Ported to ACE by Douglas C. Schmidt (schmidt@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (ACE_TOKEN_H) +#define ACE_TOKEN_H + +#include "ace/Synch.h" + +#if defined (ACE_HAS_THREADS) + +class ACE_Export ACE_Token + // = TITLE + // Class that acquires, renews, and releases a synchronization + // token that is local to the process. + // + // = DESCRIPTION + // This class is a more general-purpose synchronization mechanism + // than SunOS 5.x mutexes. For example, it implements "recursive + // mutex" semantics, where a thread that owns the token can + // reacquire it without deadlocking. In addition, threads that are + // blocked awaiting the token are serviced in strict FIFO order as + // other threads release the token (SunOS 5.x mutexes don't strictly + // enforce an acquisition order). +{ +public: + // = Initialization and termination. + + ACE_Token (const char *name = 0, void * = 0); + ~ACE_Token (void); + + // = Synchronization operations. + + int acquire (void (*sleep_hook)(void *), + void *arg = 0, + ACE_Time_Value *timeout = 0); + // Acquire the token, sleeping until it is obtained or until + // <timeout> expires. If some other thread currently holds the + // token then <sleep_hook> is called before our thread goes to + // sleep. This <sleep_hook> can be used by the requesting thread to + // unblock a token-holder that is sleeping, e.g., by means of + // writing to a pipe (the ACE ACE_Reactor uses this functionality). + // Return values: + // 0 if acquires without calling <sleep_hook> + // 1 if <sleep_hook> is called. + // -1 if failure or timeout occurs (if timeout occurs errno == ETIME) + // If <timeout> == <&ACE_Time_Value::zero> then acquire has polling + // semantics (and does *not* call <sleep_hook>). + + int acquire (ACE_Time_Value *timeout = 0); + // This behaves just like the previous <acquire> method, except + // that it invokes the virtual function called <sleep_hook> + // that can be overridden by a subclass of ACE_Token. + + virtual void sleep_hook (void); + // This should be overridden by a subclass to define + // the appropriate behavior before <acquire> goes to sleep. + // By default, this is a no-op... + + int renew (int requeue_position = 0, ACE_Time_Value *timeout = 0); + // An optimized method that efficiently reacquires the token if no + // other threads are waiting. This is useful for situations where + // you don't want to degrad the quality of service if there are + // other threads waiting to get the token. If <requeue_position> == + // -1 and there are other threads waiting to obtain the token we are + // queued at the end of the list of waiters. If <requeue_position> + // > -1 then it indicates how many entries to skip over before + // inserting our thread into the list of waiters (e.g., + // <requeue_position> == 0 means "insert at front of the queue"). + // Renew has the rather odd semantics such that if there are other + // waiting threads it will give up the token even if the + // nesting_level_ > 1. I'm not sure if this is really the right + // thing to do (since it makes it possible for shared data to be + // changed unexpectedly) so use with caution... + + int tryacquire (void); + // Become interface-compliant with other lock mechanisms (implements + // a non-blocking <acquire>). + + int remove (void); + // Shuts down the ACE_Token instance. + + int release (void); + // Relinquish the token. If there are any waiters then the next one + // in line gets it. + + // = Accessor methods. + + int waiters (void); + // Return the number of threads that are currently waiting to get + // the token. + + ACE_thread_t current_owner (void); + // Return the id of the current thread that owns the token. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + // = The following structure implements a ACE_FIFO of waiter threads + // that are asleep waiting to obtain the token. + + struct ACE_Queue_Entry + { + ACE_Queue_Entry (ACE_Thread_Mutex &m, ACE_thread_t t_id); + + ACE_Queue_Entry *next_; + // Pointer to next waiter. + + ACE_thread_t thread_id_; + // ACE_Thread id of this waiter. + + ACE_Condition_Thread_Mutex cv_; + // ACE_Condition object used to wake up waiter when it can run again. + + int runable_; + // Ok to run. + }; + + int shared_acquire (void (*sleep_hook_func)(void *), + void *arg, + ACE_Time_Value *timeout); + // Implements the <acquire> and <tryacquire> methods above. + + void remove_entry (ACE_Queue_Entry *); + // Remove a waiter from the queue (used when a timeout occurs). + + ACE_Queue_Entry *head_; + // Head of the list of waiting threads. + + ACE_Queue_Entry *tail_; + // Tail of the list of waiting threads. + + ACE_Thread_Mutex lock_; + // ACE_Thread_Mutex used to lock internal data structures. + + ACE_thread_t owner_; + // Current owner of the token. + + int in_use_; + // Some thread (i.e., <owner_>) is using the token. We need this + // extra variable to deal with POSIX pthreads madness... + + int waiters_; + // Number of waiters. + + int nesting_level_; + // Current nesting level. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Token.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_TOKEN_H */ diff --git a/ace/Token.i b/ace/Token.i new file mode 100644 index 00000000000..74669037a45 --- /dev/null +++ b/ace/Token.i @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ +// $Id$ + +// Token.i + +ACE_INLINE int +ACE_Token::remove (void) +{ + ACE_TRACE ("ACE_Token::remove"); + // Don't have an implementation for this yet... + errno = ENOTSUP; + return -1; +} + +ACE_INLINE int +ACE_Token::tryacquire (void) +{ + ACE_TRACE ("ACE_Token::tryacquire"); + return this->shared_acquire + (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero); +} + +ACE_INLINE int +ACE_Token::waiters (void) +{ + ACE_TRACE ("ACE_Token::waiters"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); + + int ret = this->waiters_; + return ret; +} + +ACE_INLINE ACE_thread_t +ACE_Token::current_owner (void) +{ + ACE_TRACE ("ACE_Token::current_owner"); + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, this->owner_); + + return this->owner_; +} + diff --git a/ace/Token_Collection.cpp b/ace/Token_Collection.cpp new file mode 100644 index 00000000000..c9f325ccb4c --- /dev/null +++ b/ace/Token_Collection.cpp @@ -0,0 +1,292 @@ +// Token_Collection.cpp +// $Id$ + + +#define ACE_BUILD_DLL +#include "ace/Token_Collection.h" +#include "ace/Log_Msg.h" + +#if !defined (__INLINE__) +#include "ace/Token_Collection.i" +#endif /* __INLINE__ */ + +ACE_Token_Collection::ACE_Token_Collection (int debug, + const char *name) +: debug_ (debug) +{ + ACE_TRACE ("ACE_Token_Collection::ACE_Token_Collection"); + + if (name == 0) + name = "no name"; + + int n = ACE_OS::strlen (name) + 1; + + if (n >= ACE_MAXTOKENNAMELEN) + n = ACE_MAXTOKENNAMELEN - 1; + + ACE_OS::strncpy (this->name_, (char *) name, n); + this->name_[ACE_MAXTOKENNAMELEN - 1] = '\0'; +} + +int +ACE_Token_Collection::insert (ACE_Token_Proxy &new_token) +{ + ACE_TRACE ("ACE_Token_Collection::insert"); + + TOKEN_NAME name (new_token.name ()); + + // Check if the new_proxy is already in the list. + if (collection_.find (name) == 1) + // One already exists, so fail. + return -1; + + // Clone the new token. + ACE_Token_Proxy *temp = new_token.clone (); + + if (collection_.bind (name, temp) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "bind failed\n"), -1); + return 0; +} + +int +ACE_Token_Collection::extract (const char *token_name, ACE_Token_Proxy *&proxy) +{ + ACE_TRACE ("ACE_Token_Collection::extract"); + TOKEN_NAME name (token_name); + return collection_.unbind (token_name, proxy); +} + +ACE_Token_Proxy * +ACE_Token_Collection::is_member (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Collection::is_member"); + TOKEN_NAME name (token_name); + ACE_Token_Proxy *temp; + // Get the token from the collection. + return collection_.find (name, temp) == -1 ? 0 : temp; +} + +int +ACE_Token_Collection::is_member (const ACE_Token_Proxy &token) +{ + ACE_TRACE ("ACE_Token_Collection::is_member"); + TOKEN_NAME token_name (token.name ()); + return collection_.find (token_name) == 0; +} + +int +ACE_Token_Collection::acquire (int notify, + void (*sleep_hook)(void *), + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Collection::acquire"); + + COLLECTION_ITERATOR iterator (collection_); + + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (debug_) + ACE_DEBUG ((LM_DEBUG, "collection acquiring %s\n", + temp->int_id_->name ())); + if (temp->int_id_->acquire (notify, sleep_hook, options) == -1) + { + int error = errno; + this->release (); + errno = error; + ACE_RETURN (-1); + } + } + + return 0; +} + +int +ACE_Token_Collection::acquire (const char *token_name, + int notify, + void (*sleep_hook)(void *), + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Collection::acquire"); + TOKEN_NAME name (token_name); + ACE_Token_Proxy *temp; + // Get the token from the collection. + int result = collection_.find (name, temp); + // did we find it? + if (result == -1) + return result; + // perform the operation + return temp->acquire (notify, sleep_hook, options); +} + + +int +ACE_Token_Collection::tryacquire (const char *token_name, + void (*sleep_hook)(void *)) +{ + ACE_TRACE ("ACE_Token_Collection::tryacquire"); + TOKEN_NAME name (token_name); + ACE_Token_Proxy *temp; + // Get the token from the collection. + int result = collection_.find (name, temp); + // did we find it? + if (result == -1) + return result; + + // perform the operation + return temp->tryacquire (sleep_hook); +} + +int +ACE_Token_Collection::tryacquire (void (*sleep_hook)(void *)) +{ + ACE_TRACE ("ACE_Token_Collection::tryacquire"); + + COLLECTION_ITERATOR iterator (collection_); + + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (debug_) + ACE_DEBUG ((LM_DEBUG, "collection acquiring %s\n", + temp->int_id_->name ())); + // We will fail if _any_ token is not free. + if (temp->int_id_->tryacquire (sleep_hook) == -1) + return -1; + } + + return 0; +} + +int +ACE_Token_Collection::renew (int requeue_position, + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Collection::renew"); + + COLLECTION_ITERATOR iterator (collection_); + + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (debug_) + ACE_DEBUG ((LM_DEBUG, "collection renewing %s\n", + temp->int_id_->name ())); + if (temp->int_id_->renew (requeue_position, options) == -1) + return -1; + } + + return 0; +} + +int +ACE_Token_Collection::renew (const char *token_name, + int requeue_position, + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Collection::renew"); + TOKEN_NAME name (token_name); + ACE_Token_Proxy *temp; + + // Get the token from the collection. + int result = collection_.find (name, temp); + + // Did we find it? + if (result == -1) + ACE_ERROR_RETURN ((LM_DEBUG, "%p %s\n", + "not in collection ", + token_name), -1); + // perform the operation + return temp->renew (requeue_position, options); +} + +int +ACE_Token_Collection::release (ACE_Synch_Options &options) + +{ + ACE_TRACE ("ACE_Token_Collection::release"); + COLLECTION_ITERATOR iterator (collection_); + + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (debug_) + ACE_DEBUG ((LM_DEBUG, "collection releasing %s\n", + temp->int_id_->name ())); + temp->int_id_->release (); + } + + return 0; +} + +int +ACE_Token_Collection::release (const char *token_name, + ACE_Synch_Options &options) +{ + ACE_TRACE ("ACE_Token_Collection::release"); + TOKEN_NAME name (token_name); + ACE_Token_Proxy *temp; + // get the token from the collection + int result = collection_.find (name, temp); + // did we find it? + if (result != 0) + return result; + // perform the operation + return temp->release (options); +} + +ACE_Token_Collection::~ACE_Token_Collection (void) +{ + ACE_TRACE ("ACE_Token_Collection::~ACE_Token_Collection"); + COLLECTION_ITERATOR iterator (collection_); + + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + delete temp->int_id_; + // The ext_id_'s delete themselves when the array of + // COLLECTION_ENTRYs goes away. + } +} + + +// This method doesn't mean anything for a collection. +ACE_Token_Proxy * +ACE_Token_Collection::clone (void) const +{ + ACE_TRACE ("ACE_Token_Collection::clone"); + return (ACE_Token_Proxy *) 0; +} + +// This method doesn't mean anything for a collection. +ACE_Tokens * +ACE_Token_Collection::create_token (const char *name) +{ + ACE_TRACE ("ACE_Token_Collection::create_token"); + return (ACE_Tokens *) 0; +} + +void +ACE_Token_Collection::dump (void) const +{ + ACE_TRACE ("ACE_Token_Collection::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Collection::dump:\n" + " debug_ = %d\n", debug_)); + ACE_DEBUG ((LM_DEBUG, "collection_\n")); + collection_.dump (); + ACE_DEBUG ((LM_DEBUG, "base:\n")); + ACE_Token_Proxy::dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Map_Manager<ACE_Token_Name, ACE_Token_Proxy *, ACE_Null_Mutex>; +template class ACE_Map_Iterator<ACE_Token_Name, ACE_Token_Proxy *, ACE_Null_Mutex>; +template class ACE_Map_Entry<ACE_Token_Name, ACE_Token_Proxy *>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Token_Collection.h b/ace/Token_Collection.h new file mode 100644 index 00000000000..c31147c927e --- /dev/null +++ b/ace/Token_Collection.h @@ -0,0 +1,216 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// ACE_Token_Collection.h +// +// = DESCRIPTION +// The ACE_Token class offers methods for acquiring, renewing, +// and releasing a synchronization token on a per-token basis. The +// ACE_Token_Collection offers an interface for performing +// operations on groups of tokens as a whole, or on a single token +// within the collection. +// +// The atomic group operations are not yet implemented. +// +// = AUTHOR +// Douglas C. Schmidt (schmidt@cs.wustl.edu) and +// Tim Harrison (harrison@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (ACE_TOKEN_COLLECTION_H) +#define ACE_TOKEN_COLLECTION_H + +#include "ace/Map_Manager.h" +#include "ace/Local_Tokens.h" +#include "ace/SString.h" + +class ACE_Export ACE_Token_Collection : public ACE_Token_Proxy + // = TITLE + // Allows atomic token group operations AND + // provides a ACE_Token manager interface. + // + // = DESCRIPTION + // There are two types of operations offered by + // ACE_Token_Collection. The first is atomic operations on + // collections of Token_Proxies. In this respect, the + // ACE_Token_Collection can be thought of as a single token + // consisting of multiple Token_Proxies. The second role of the + // ACE_Token_Collection is as a ACE_Token manager. + // ACE_Token_Collection allows individual operations on single + // members of a collection of Token_Proxies. This provides a + // single access point for operations on multiple tokens. + + // = Bugs + // Although ACE_Token_Collection inherits from ACE_Token_Proxy, it + // can not be including in a collection. This is because clone() + // returns zero for now. + +{ +public: + + ACE_Token_Collection (int debug = 0, + const char *name = 0); + // <debug> print out verbose debugging messages. <name> will give a + // name to the collection. Collections don't really need names, but + // are sometimes useful for debugging. + +// Collection Management operations + + int insert (ACE_Token_Proxy &token); + + // Insert a Token into the collection. All ACE_Token type + // operations performed on the collection will also be performed on + // the new_proxy until it is removed. Note that no operations + // performed prior to the insertion will be performed. Returns: 0 + // on success, -1 on failure with <errno> == problem. If a token + // proxy already exists in the collection with the same name, the + // insertion will fail. Also, <token> is copied. Note that during + // the copy, client_id's are *not* inherited. The client ID of the + // thread using the collection will be used. Client ID's can be + // changed explicity on each proxy using is_member. + + int extract (const char *token_name, ACE_Token_Proxy *&proxy); + // removes the ACE_Token matching the given token_name from the + // collection. On success, extract returns 0. On failure + // (token_name was not in the collection,) extract returns -1. On + // success, the state of the token found is copied into proxy. + // The returned ACE_Token_Proxy* must be deleted by the user. + + ACE_Token_Proxy *is_member (const char *token_name); + // returns the proxy if true. 0 otherwise. + + int is_member (const ACE_Token_Proxy &token); + // Is the specified token in the collection? + // 1, yes. + // 0, no. + +// = Collective operation semantics. + +// For acquire, renew, and release, there are two interfaces. Once +// interface allows an operation on a single token in the +// collection. The collective interfaces perform atomic operations +// on the entire collection. For instance, a collective acquire +// will perform an acquire for each and every token in the +// collection or the operation will fail. Currently, these +// operations are performed with no ordering heuristics. That is, +// the Collection steps through the tokens in the order they were +// inserted. For each one it performs the operation (acquire, +// renew, or release). + + virtual int acquire (int notify = 0, + void (*sleep_hook)(void *) = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Acquire "atomically" all resources in the collection. This is + // only successfull if all tokens in the collection could be + // acquired. options contains the blocking semantics, timeout + // value, etc. Returns: 0 on success, -1 on failure with <errno> == + // problem. If and error or deadlock occurs for one of the tokens, + // all the tokens will be released and the method will return -1. + // Note that returning on detection of deadlock prevents livelock + // between competing collections. If a collection returns after + // detecting deadlock, it is the application's responsibility to not + // to blindly loop on the collection::acquire operation. In other + // words, once the collection reports deadlock, it is out of our + // hands. + + virtual int acquire (const char *token_name, + int notify = 0, + void (*sleep_hook)(void *) = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Acquire the token corresponding to <token_name>. The other + // parameters are passed to <token>::acquire. + + virtual int tryacquire (void (*sleep_hook)(void *) = 0); + // Try to acquire all tokens in collection. + + virtual int tryacquire (const char *token_name, + void (*sleep_hook)(void *) = 0); + // Try to acquire <token_name>. + + virtual int renew (int requeue_position = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Renews "atomically" all resources in the collection. This is + // only successfull if all tokens in the collection could be + // renewed. options contains the blocking semantics, timeout + // value, etc. Returns: 0 on success, -1 on failure with <errno> == + // problem. + + + virtual int renew (const char *token_name, + int requeue_position = 0, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Renew the token corresponding to <token_name>. The other + // parameters are passed to <token>::renew. + + virtual int release (ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Releases "atomically" all resources in the collection. This is + // only successfull if all tokens in the collection could be + // released. options contains the blocking semantics, timeout + // value, etc. Returns: 0 on success, -1 on failure with <errno> == + // problem. + + + virtual int release (const char *token_name, + ACE_Synch_Options &options = + ACE_Synch_Options::defaults); + // Release the token corresponding to <token_name>. The other + // parameters are passed to <token>::release. + + ~ACE_Token_Collection (void); + + void dump (void) const; + // Dump the state of the class. + + virtual const char *name (void) const; + // Return the name of the collection. Not very functionally + // important, but sometimes a useful debugging tool. + +protected: + + typedef ACE_Token_Name TOKEN_NAME; + + typedef ACE_Map_Manager<TOKEN_NAME, ACE_Token_Proxy *, ACE_Null_Mutex> + COLLECTION; + // COLLECTION maintains a mapping from token names to ACE_Tokens* + + typedef ACE_Map_Iterator<TOKEN_NAME, ACE_Token_Proxy *, ACE_Null_Mutex> + COLLECTION_ITERATOR; + // Allows iterations through collection_ + + typedef ACE_Map_Entry<TOKEN_NAME, ACE_Token_Proxy *> + COLLECTION_ENTRY; + // Allows iterations through collection_ + + COLLECTION collection_; + // COLLECTION maintains a mapping from token names to ACE_Tokens*. + + int debug_; + // Whether to print out debug messages or not. + + char name_[ACE_MAXTOKENNAMELEN]; + // Name of the collection. + + // = I'm not sure what these mean, but they have to be defined since they're + // pure virtual in ACE_Token_Proxy. + virtual ACE_Token_Proxy *clone (void) const; + virtual ACE_Tokens *create_token (const char *name); +}; + +#if defined (__INLINE__) +#include "ace/Token_Collection.i" +#endif /* __INLINE__ */ + +#endif /* ACE_TOKEN_COLLECTION_H */ diff --git a/ace/Token_Collection.i b/ace/Token_Collection.i new file mode 100644 index 00000000000..f871206c4d8 --- /dev/null +++ b/ace/Token_Collection.i @@ -0,0 +1,11 @@ +/* -*- C++ -*- */ +// $Id$ + +// Token_Collection.i + +ACE_INLINE const char * +ACE_Token_Collection::name (void) const +{ + return name_; +} + diff --git a/ace/Token_Invariants.cpp b/ace/Token_Invariants.cpp new file mode 100644 index 00000000000..5687d0dfe37 --- /dev/null +++ b/ace/Token_Invariants.cpp @@ -0,0 +1,338 @@ +// Token_Invariants.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Token_Invariants.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Token_Invariants.i" +#endif /* __ACE_INLINE__ */ + +ACE_Token_Invariant_Manager * +ACE_Token_Invariant_Manager::instance (void) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::instance"); + static ACE_Token_Invariant_Manager *instance = 0; + + static ACE_TOKEN_CONST::MUTEX lock; + + // Perform the Double-Check pattern... + if (instance == 0) + { + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, lock, 0); + + if (instance == 0) + ACE_NEW_RETURN (instance, ACE_Token_Invariant_Manager, 0); + } + + return instance; +} + +ACE_Token_Invariant_Manager::ACE_Token_Invariant_Manager (void) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::ACE_Token_Invariant_Manager"); +} + +int +ACE_Token_Invariant_Manager::mutex_acquired (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::mutex_acquired"); + + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + ACE_Mutex_Invariants *inv = 0; + if (this->get_mutex (token_name, inv) == -1) + return -1; + else + return inv->acquired (); +} + +int +ACE_Token_Invariant_Manager::acquired (const ACE_Token_Proxy *proxy) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::acquired"); + + // Reach into the proxy to find the token type. + if (proxy->token_->type () == ACE_Tokens::MUTEX) + return this->mutex_acquired (proxy->name ()); + else // ACE_Tokens::RWLOCK. + { + if (proxy->type () == ACE_RW_Token::READER) + return this->reader_acquired (proxy->name ()); + else // ACE_RW_Token::WRITER. + return this->writer_acquired (proxy->name ()); + } +} + +void +ACE_Token_Invariant_Manager::releasing (const ACE_Token_Proxy *proxy) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::releasing"); + + // Reach into the proxy to find the token type. + if (proxy->token_->type () == ACE_Tokens::MUTEX) + this->mutex_releasing (proxy->name ()); + else // ACE_Tokens::RWLOCK. + this->rwlock_releasing (proxy->name ()); +} + +void +ACE_Token_Invariant_Manager::mutex_releasing (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::mutex_releasing"); + ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_); + + ACE_Mutex_Invariants *inv = 0; + if (this->get_mutex (token_name, inv) == 0) + inv->releasing (); +} + +int +ACE_Token_Invariant_Manager::reader_acquired (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::reader_acquired"); + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + ACE_RWLock_Invariants *inv = 0; + if (this->get_rwlock (token_name, inv) == -1) + return -1; + else + return inv->reader_acquired (); +} + +int +ACE_Token_Invariant_Manager::writer_acquired (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::writer_acquired"); + + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1); + + ACE_RWLock_Invariants *inv = 0; + if (this->get_rwlock (token_name, inv) == -1) + return -1; + else + return inv->writer_acquired (); +} + +void +ACE_Token_Invariant_Manager::rwlock_releasing (const char *token_name) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::rwlock_releasing"); + + ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_); + + ACE_RWLock_Invariants *inv = 0; + if (this->get_rwlock (token_name, inv) == 0) + inv->releasing (); +} + +void +ACE_Token_Invariant_Manager::dump (void) const +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "mutex_collection_:\n")); + mutex_collection_.dump (); + ACE_DEBUG ((LM_DEBUG, "rwlock_collection_:\n")); + rwlock_collection_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + + +int +ACE_Token_Invariant_Manager::get_mutex (const char *token_name, + ACE_Mutex_Invariants *&inv) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::get_mutex"); + TOKEN_NAME name (token_name); + if (mutex_collection_.find (name, inv) == -1) + // We did not find one in the collection. + { + ACE_Mutex_Invariants *new_invariant; + + ACE_NEW_RETURN (new_invariant, ACE_Mutex_Invariants, -1); + + if (mutex_collection_.bind (name, new_invariant) == -1) + { + delete new_invariant; + return -1; + } + + if (mutex_collection_.find (name, inv) == -1) + // We did not find one in the collection. + return -1; + } + + return 0; +} + +int +ACE_Token_Invariant_Manager::get_rwlock (const char *token_name, + ACE_RWLock_Invariants *&inv) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::get_rwlock"); + TOKEN_NAME name (token_name); + if (rwlock_collection_.find (name, inv) == -1) + // We did not find one in the collection. + { + ACE_RWLock_Invariants *new_invariant; + + ACE_NEW_RETURN (new_invariant, ACE_RWLock_Invariants, -1); + + if (rwlock_collection_.bind (name, new_invariant) == -1) + return -1; + + if (rwlock_collection_.find (name, inv) == -1) + // We did not find one in the collection. + return -1; + } + + return 0; +} + + +ACE_Token_Invariant_Manager::~ACE_Token_Invariant_Manager (void) +{ + ACE_TRACE ("ACE_Token_Invariant_Manager::~ACE_Token_Invariant_Manager"); + MUTEX_COLLECTION_ITERATOR iterator (mutex_collection_); + + for (MUTEX_COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + delete temp->int_id_; + + RWLOCK_COLLECTION_ITERATOR iterator2 (rwlock_collection_); + + for (RWLOCK_COLLECTION_ENTRY *temp2 = 0; + iterator2.next (temp2) != 0; + iterator2.advance ()) + delete temp2->int_id_; +} + +// ************************************************** +// ************************************************** +// ************************************************** + +ACE_Mutex_Invariants::ACE_Mutex_Invariants (void) +: owners_ (0) +{ +} + +int +ACE_Mutex_Invariants::acquired (void) +{ + if (++owners_ > 1) + { + owners_ = 42; + return 0; + } + else + return 1; +} + +void +ACE_Mutex_Invariants::releasing (void) +{ + if (owners_ == 1) + --owners_; +} + +ACE_Mutex_Invariants::ACE_Mutex_Invariants (const ACE_Mutex_Invariants &rhs) +: owners_ (rhs.owners_) +{ +} + +void +ACE_Mutex_Invariants::operator= (const ACE_Mutex_Invariants &rhs) +{ + owners_ = rhs.owners_; +} + +void +ACE_Mutex_Invariants::dump (void) const +{ + ACE_TRACE ("ACE_Mutex_Invariants::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "owners_ = %d\n", owners_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************** +// ************************************************** +// ************************************************** + +ACE_RWLock_Invariants::ACE_RWLock_Invariants (void) +: writers_ (0), + readers_ (0) +{ +} + +int +ACE_RWLock_Invariants::writer_acquired (void) +{ + if (readers_ > 0) + { + writers_ = readers_ = 42; + return 0; + } + else if (++writers_ > 1) + { + writers_ = readers_ = 42; + return 0; + } + else + return 1; +} + +int +ACE_RWLock_Invariants::reader_acquired (void) +{ + if (writers_ > 0) + { + writers_ = readers_ = 42; + return 0; + } + else + { + ++readers_; + return 1; + } +} + +void +ACE_RWLock_Invariants::releasing (void) +{ + if (writers_ == 1) + writers_ = 0; + else if (readers_ > 0) + --readers_; +} + +ACE_RWLock_Invariants::ACE_RWLock_Invariants (const ACE_RWLock_Invariants &rhs) +: writers_ (rhs.writers_), + readers_ (rhs.readers_) +{ +} + +void +ACE_RWLock_Invariants::operator= (const ACE_RWLock_Invariants &rhs) +{ + writers_ = rhs.writers_; + readers_ = rhs.readers_; +} + +void +ACE_RWLock_Invariants::dump (void) const +{ + ACE_TRACE ("ACE_RWLock_Invariants::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "writers_ = %d\n", + "readers_ = %d\n", + writers_, readers_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +// template class ACE_TSS <ACE_TPQ_Entry>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Token_Invariants.h b/ace/Token_Invariants.h new file mode 100644 index 00000000000..eb40c9524a0 --- /dev/null +++ b/ace/Token_Invariants.h @@ -0,0 +1,217 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Token_Invariants +// +// = AUTHOR +// Tim Harrison (harrison@cs.wustl.edu) +// +// = DESCRIPTION +// Allows applications to test that invariants are always +// satisfied. Can test mutexes and readers/writer locks. Does +// not test recursive acquisition. +// +// ============================================================================ + +#if !defined (ACE_TOKEN_INVARIANTS_H) +#define ACE_TOKEN_INVARIANTS_H + +#include "ace/Synch.h" +#include "ace/Map_Manager.h" +#include "ace/Local_Tokens.h" + + +class ACE_Mutex_Invariants + // = TITLE + // Mutex Invariants + // + // = INVARIANTS + // 1. Only one owner at a time. +{ +public: + ACE_Mutex_Invariants (void); + // Default construction. + + int acquired (void); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + void releasing (void); + // Updates internal database. + + // = Map_Manager operations. + + ACE_Mutex_Invariants (const ACE_Mutex_Invariants &rhs); + // Copy construction. + + void operator= (const ACE_Mutex_Invariants &rhs); + // Copy. + + void dump (void) const; + // Dump the state of the class. + +private: + int owners_; + // Number of owners. This had better be 0 >= owners_ <= 1; +}; + +class ACE_RWLock_Invariants + // = TITLE + // RWLock Invariants + // + // = INVARIANTS + // 1. Only one writer at a time. + // 2. If there is an owning writer, there are no owning readers. +{ +public: + ACE_RWLock_Invariants (void); + // Default construction. + + int writer_acquired (void); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + int reader_acquired (void); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + void releasing (void); + // Updates internal database. + + // = Map_Manager operations. + + ACE_RWLock_Invariants (const ACE_RWLock_Invariants &rhs); + // Copy construction. + + void operator= (const ACE_RWLock_Invariants &rhs); + // Copy. + + void dump (void) const; + // Dump the state of the class. + +private: + int readers_; + // Number of owning readers. + + int writers_; + // Number of owning writers. +}; + +class ACE_Export ACE_Token_Invariant_Manager + // = TITLE + // Token Invariants + // + // = DESCRIPTION + // The Token Invariant Manager allows applications to test that + // invariants are always satisfied. Currently, Token_Invariants + // can test mutexes and readers/writer locks. Does not test + // recursive acquisition. + // + // Note that this class does not ever clean its database. Until + // destroyed, it's size will forever increase. +{ +public: + + static ACE_Token_Invariant_Manager *instance (void); + // Singleton access point. + + // = Polymorphic methods. Just pass in the proxy and the method + // figures out the type of the token. + + int acquired (const ACE_Token_Proxy *proxy); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + void releasing (const ACE_Token_Proxy *proxy); + // Updates internal database. + + // = Explicit methods. These to not require actual proxies in order + // to test a scenario. + + int mutex_acquired (const char *token_name); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + void mutex_releasing (const char *token_name); + // Updates internal database. + + int reader_acquired (const char *token_name); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + int writer_acquired (const char *token_name); + // Returns 1 on success, 0 when an invariant has been violated and + // -1 on error. + + void rwlock_releasing (const char *token_name); + // Updates internal database. + + void dump (void) const; + // Dump the state of the class. + + // = The following two method should be in the protected part of the + // class. Bugs with certain compilers preclude this. + ACE_Token_Invariant_Manager (void); + // Prevent non-singleton construction. + + ~ACE_Token_Invariant_Manager (void); + // Destruction. + +protected: + int get_mutex (const char *token_name, + ACE_Mutex_Invariants *&inv); + // Return or create. + + int get_rwlock (const char *token_name, + ACE_RWLock_Invariants *&inv); + // Return or create. + + ACE_TOKEN_CONST::MUTEX lock_; + // ACE_Mutex_Token used to lock internal data structures. + + typedef ACE_Token_Name TOKEN_NAME; + // This may be changed to a template type. + + typedef ACE_Map_Manager<TOKEN_NAME, ACE_Mutex_Invariants *, ACE_Null_Mutex> + MUTEX_COLLECTION; + // COLLECTION maintains a mapping from token names to mutexes. + + typedef ACE_Map_Iterator<TOKEN_NAME, ACE_Mutex_Invariants *, ACE_Null_Mutex> + MUTEX_COLLECTION_ITERATOR; + // Allows iterations through collection. + + typedef ACE_Map_Entry<TOKEN_NAME, ACE_Mutex_Invariants *> + MUTEX_COLLECTION_ENTRY; + // Allows iterations through collection. + + MUTEX_COLLECTION mutex_collection_; + // MUTEX_COLLECTION maintains a mapping from token names to mutexes. + + typedef ACE_Map_Manager<TOKEN_NAME, ACE_RWLock_Invariants *, ACE_Null_Mutex> + RWLOCK_COLLECTION; + // COLLECTION maintains a mapping from token names to mutexes. + + typedef ACE_Map_Iterator<TOKEN_NAME, ACE_RWLock_Invariants *, ACE_Null_Mutex> + RWLOCK_COLLECTION_ITERATOR; + // Allows iterations through collection. + + typedef ACE_Map_Entry<TOKEN_NAME, ACE_RWLock_Invariants *> + RWLOCK_COLLECTION_ENTRY; + // Allows iterations through collection. + + RWLOCK_COLLECTION rwlock_collection_; + // MUTEX_COLLECTION maintains a mapping from token names to mutexes. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Token_Invariants.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_TOKEN_INVARIANTS_H */ diff --git a/ace/Token_Invariants.i b/ace/Token_Invariants.i new file mode 100644 index 00000000000..53e10294181 --- /dev/null +++ b/ace/Token_Invariants.i @@ -0,0 +1,4 @@ +/* -*- C++ -*- */ +// $Id$ + +// Token_Invariants.i diff --git a/ace/Token_Manager.cpp b/ace/Token_Manager.cpp new file mode 100644 index 00000000000..b144a71505a --- /dev/null +++ b/ace/Token_Manager.cpp @@ -0,0 +1,259 @@ +// Token_Manager.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Token_Manager.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Token_Manager.i" +#endif /* __ACE_INLINE__ */ + +// singleton token manager +ACE_Token_Manager *ACE_Token_Manager::token_manager_ = 0; + +ACE_TOKEN_CONST::MUTEX ACE_Token_Manager::creation_lock_; + +ACE_Token_Manager::ACE_Token_Manager () +{ + ACE_TRACE ("ACE_Token_Manager::ACE_Token_Manager"); +} + +ACE_Token_Manager::~ACE_Token_Manager () +{ + ACE_TRACE ("ACE_Token_Manager::~ACE_Token_Manager"); + + COLLECTION_ITERATOR iterator (collection_); + + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + // @ should I be doing an unbind here? + delete temp->int_id_; + // The ext_id_'s delete themselves when the array of + // COLLECTION_ENTRYs goes away. + } +} + +ACE_Token_Manager * +ACE_Token_Manager::instance (void) +{ + ACE_TRACE ("ACE_Token_Manager::token_manager"); + + // This first check is to avoid acquiring the mutex in the common + // case. Double-Check pattern rules. + if (token_manager_ == 0) + { + ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, ACE_Token_Manager::creation_lock_, 0); + + if (token_manager_ == 0) + ACE_NEW_RETURN (token_manager_, ACE_Token_Manager, 0); + } + + return token_manager_; +} + +void +ACE_Token_Manager::get_token (ACE_Token_Proxy *proxy, + const char *token_name) +{ + ACE_TRACE ("ACE_Token_Manager::get"); + // Hmm. I think this makes sense. We perform our own locking here + // (see safe_acquire.) We have to make sure that only one thread + // uses the collection at a time. + + ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_); + + TOKEN_NAME name (token_name); + + if (collection_.find (name, proxy->token_) == -1) + // We did not find one in the collection. + { + // Make one. + proxy->token_ = proxy->create_token (token_name); + + // Put it in the collection. + if (collection_.bind (name, proxy->token_) == -1) + { + delete proxy->token_; + proxy->token_ = 0; + } + } + + if (proxy->token_ != 0) + proxy->token_->inc_reference (); + + // We may be returning proxy->token_ == 0 if new failed, caller must + // check. +} + +// 0. check_deadlock (TOKEN) +// 1. if TOKEN->visited (), return 0. +// 2. mark TOKEN visited. +// 3. get ALL_OWNERS +// 4. if CLIENT in ALL_OWNERS, return *DEADLOCK*. +// 5. for each OWNER in ALL_OWNERS, +// 6. if OWNER is not waiting for a NEW_TOKEN, continue. +// 7. else, if check_deadlock (NEW_TOKEN) == 1, return *DEADLOCK* +// 8. return 0. + +int +ACE_Token_Manager::check_deadlock (ACE_Token_Proxy *proxy) +{ + ACE_TRACE ("ACE_Token_Manager::check_deadlock"); + + // Start the recursive deadlock detection algorithm. + int result = this->check_deadlock (proxy->token_, proxy); + + // Whether or not we detect deadlock, we have to unmark all tokens + // for the next time. + COLLECTION_ITERATOR iterator (collection_); + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + temp->int_id_->visit (0); + + return result; +} + +int +ACE_Token_Manager::check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy) +{ + ACE_TRACE ("ACE_Token_Manager::check_deadlock"); + + if (token->visited ()) + return 0; + + token->visit (1); + + ACE_Tokens::OWNER_STACK owners; + + int is_owner = token->owners (owners, proxy->client_id ()); + + switch (is_owner) + { + case -1: + // Error. + return -1; + case 1: + // The caller is an owner, so we have a deadlock situation. + if (debug_) + { + ACE_DEBUG ((LM_DEBUG, "(%t) Deadlock detected.\n")); + ACE_DEBUG ((LM_DEBUG, "%s owns %s and is waiting for %s.\n", + proxy->client_id (), + token->name (), + proxy->token_->name ())); + } + + return 1; + case 0: + default: + // Recurse on each owner. + while (!owners.is_empty ()) + { + ACE_TPQ_Entry *e; + owners.pop (e); + // If the owner is waiting on another token, recurse. + ACE_Tokens *twf = this->token_waiting_for (e->client_id ()); + if ((twf != 0) && + (this->check_deadlock (twf, proxy) == 1)) + { + if (debug_) + { + ACE_DEBUG ((LM_DEBUG, + "%s owns %s and is waiting for %s.\n", + e->client_id (), + token->name (), + twf->name ())); + } + return 1; + } + // else, check the next owner. + } + + // We've checked all the owners and found no deadlock. + return 0; + } +} + + +ACE_Tokens * +ACE_Token_Manager::token_waiting_for (const char *client_id) +{ + COLLECTION_ITERATOR iterator (collection_); + for (COLLECTION_ENTRY *temp = 0; + iterator.next (temp) != 0; + iterator.advance ()) + { + if (temp->int_id_->is_waiting_for (client_id)) + return temp->int_id_; + } + + // nothing was found, return NULL. + return 0; +} + +// Notify the token manager that a token is has been released. If +// as a result, there is no owner of the token, the token is +// deleted. +void +ACE_Token_Manager::release_token (ACE_Tokens *&token) +{ + ACE_TRACE ("ACE_Token_Manager::release"); + // again, let's perform our own locking here. + + ACE_GUARD (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_); + + if (token->dec_reference () == 0) + { + // No one has the token, so we can delete it and remove it from + // our collection. First, let's get it from the collection. + TOKEN_NAME token_name (token->name ()); + + ACE_Tokens *temp; + + if (collection_.unbind (token_name, temp) == -1) + // we did not find one in the collection + { + errno = ENOENT; + ACE_ERROR ((LM_ERROR, "Token Manager could not release %s:%d\n", + token->name (), token->type ())); + // @@ bad + } + else + // we found it + { + // sanity pointer comparison. The token referenced by the + // proxy better be the one we found in the list. + ACE_ASSERT (token == temp); + delete token; // or delete temp + // we set their token to zero. if the calling proxy is + // still going to be used, it had better check it's token + // value before calling a method on it! + token = 0; + } + } + // else + // someone is still interested in the token, so keep it around. +} + +void +ACE_Token_Manager::dump (void) const +{ + ACE_TRACE ("ACE_Token_Manager::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "ACE_Token_Manager::dump:\n")); + ACE_DEBUG ((LM_DEBUG, "lock_\n")); + lock_.dump (); + ACE_DEBUG ((LM_DEBUG, "collection_\n")); + collection_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +template class ACE_Map_Manager <ACE_Token_Name, ACE_Tokens *, ACE_Null_Mutex>; +template class ACE_Map_Iterator<ACE_Token_Name, ACE_Tokens *, ACE_Null_Mutex>; +template class ACE_Map_Entry <ACE_Token_Name, ACE_Tokens *>; +#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Token_Manager.h b/ace/Token_Manager.h new file mode 100644 index 00000000000..d1f004ab06f --- /dev/null +++ b/ace/Token_Manager.h @@ -0,0 +1,124 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Token_Manager +// +// = AUTHOR +// Tim Harrison (harrison@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (ACE_TOKEN_MANAGER_H) +#define ACE_TOKEN_MANAGER_H + +#include "ace/Synch.h" +#include "ace/Map_Manager.h" +#include "ace/Local_Tokens.h" + +class ACE_Local_Mutex; +class ACE_Mutex_Token; + +class ACE_Export ACE_Token_Manager +// = TITLE +// Manages all tokens in a process space. +// +// = DESCRIPTION +// Factory: Proxies use the token manager to obtain token +// references. This allows multiple proxies to reference the same +// logical token. +// Deadlock detection: Tokens use the manager to check for +// deadlock situations during acquires. +// = EXTENDING TOKENS +// To add a new type of token (e.g. semaphore), do the following +// steps: 1. Create a new derivation of ACE_Token. This class +// defines the semantics of the new Token. 2. Create a +// derivation of ACE_Token_Manager. You will only need to +// redefine make_mutex. +{ +public: + ACE_Token_Manager (void); + ~ACE_Token_Manager (void); + + // Set/get a pointer to token manager singleton. + static ACE_Token_Manager *instance (void); + void instance (ACE_Token_Manager *); + + void get_token (ACE_Token_Proxy *, const char *token_name); + // The Token manager uses ACE_Token_Proxy::token_id_ to look for + // an existing token. If none is found, the Token Manager calls + // ACE_Token_Proxy::create_token to create a new one. When + // finished, sets ACE_Token_Proxy::token_. <token_name> uniquely + // id's the token name. + + int check_deadlock (ACE_Token_Proxy *proxy); + int check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy); + // returns 1 if the acquire will _not_ cause deadlock. + // returns 0 if the acquire _will_ cause deadlock. + // this method ignores recursive acquisition. That is, it will not + // report deadlock if the client holding the token requests the + // token again. Thus, it assumes recursive mutexes. + + void release_token (ACE_Tokens *&token); + // notify the token manager that a token has been released. If as a + // result, there is no owner of the token, the token is deleted. + + ACE_TOKEN_CONST::MUTEX &mutex (void); + // This is to allow Tokens to perform atomic transactions. The + // typical usage is to acquire this mutex, check for a safe_acquire, + // perform some queueing (if need be) and then release the lock. + // This is necessary since safe_acquire is implemented in terms of + // the Token queues. + + void dump (void) const; + // Dump the state of the class. + + void debug (int d); + // Turn debug mode on/off. + +private: + int debug_; + // Wether to print debug messages or not. + + static ACE_Token_Manager *token_manager_; + // pointer to singleton token manager. + + static ACE_TOKEN_CONST::MUTEX creation_lock_; + // make sure that token_manager_ is created atomically (only once!) + + ACE_Tokens *token_waiting_for (const char *client_id); + // return the token that the given client_id is waiting for, if any + + ACE_TOKEN_CONST::MUTEX lock_; + // ACE_Mutex_Token used to lock internal data structures. + + typedef ACE_Token_Name TOKEN_NAME; + // This may be changed to a template type. + + typedef ACE_Map_Manager<TOKEN_NAME, ACE_Tokens *, ACE_Null_Mutex> + COLLECTION; + // COLLECTION maintains a mapping from token names to ACE_Tokens* + + typedef ACE_Map_Iterator<TOKEN_NAME, ACE_Tokens *, ACE_Null_Mutex> + COLLECTION_ITERATOR; + // Allows iterations through collection_ + + typedef ACE_Map_Entry<TOKEN_NAME, ACE_Tokens *> + COLLECTION_ENTRY; + // Allows iterations through collection_ + + COLLECTION collection_; + // COLLECTION maintains a mapping from token names to ACE_Tokens*. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Token_Manager.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_TOKEN_MANAGER_H */ diff --git a/ace/Token_Manager.i b/ace/Token_Manager.i new file mode 100644 index 00000000000..572d439f289 --- /dev/null +++ b/ace/Token_Manager.i @@ -0,0 +1,19 @@ +/* -*- C++ -*- */ +// $Id$ + +// Token_Manager.i + +ACE_INLINE ACE_TOKEN_CONST::MUTEX & +ACE_Token_Manager::mutex (void) +{ + ACE_TRACE ("ACE_Token_Manager::mutex"); + return lock_; +} + +ACE_INLINE void +ACE_Token_Manager::debug (int d) +{ + ACE_TRACE ("ACE_Token_Manager::debug"); + debug_ = d; +} + diff --git a/ace/Token_Request_Reply.cpp b/ace/Token_Request_Reply.cpp new file mode 100644 index 00000000000..1aa160466ad --- /dev/null +++ b/ace/Token_Request_Reply.cpp @@ -0,0 +1,167 @@ +// Token_Request_Reply.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Token_Request_Reply.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Token_Request_Reply.i" +#endif /* __ACE_INLINE__ */ + +// Default "do nothing" constructor. + +ACE_Token_Request::ACE_Token_Request (void) + : client_id_ (0), + token_name_ (0) +{ +} + +// Create a ACE_Token_Request message. + +ACE_Token_Request::ACE_Token_Request (int token_type, + int proxy_type, + ACE_UINT32 operation_type, + const char token_name[], + const char client_id[], + const ACE_Synch_Options &options) +{ + this->token_type (token_type); + this->proxy_type (proxy_type); + this->operation_type (operation_type); + this->options (options); + this->token_name (token_name, client_id); +} + +// Encode the transfer buffer into network byte order +// so that it can be sent to the server. + +int +ACE_Token_Request::encode (void *&buf) +{ + buf = (void *) &this->transfer_; + return this->length (); +} + +// Decode the transfer buffer into host byte byte order +// so that it can be used by the server. + +int +ACE_Token_Request::decode (void) +{ + this->token_name_ = this->transfer_.data_; + + options_.set (transfer_.use_timeout_ == 1 ? ACE_Synch_Options::USE_TIMEOUT : 0, + ACE_Time_Value (transfer_.sec_, transfer_.usec_), + (void *) transfer_.arg_); + + // Decode the variable-sized portion. + int token_len = ACE_OS::strlen (this->token_name_); + + // Check to make sure this->tokenName_ isn't too long! + if (token_len >= ACE_MAXTOKENNAMELEN) + { + errno = ENAMETOOLONG; + return -1; + } + else // Skip this->tokenName_ + '\0' + ':'. + this->client_id_ = &this->token_name_[token_len + 2]; + + size_t data_size = ((sizeof this->transfer_ + - sizeof this->transfer_.data_) // Fixed-size header. + + ACE_OS::strlen (this->token_name_) + 1 // this->tokenName_ + '\0' + + ACE_OS::strlen (this->client_id_) + 1 // this->clientId_ + '\0' + + 1); // Space for ':' + // Make sure the message was correctly received and framed. + return this->length () == data_size ? 0 : -1; +} + +// Print out the current values of the ACE_Token_Request. + +void +ACE_Token_Request::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, "*******\nlength = %d\ntoken name = %s\nclient id = %s\n", + this->length (), this->token_name (), this->client_id ())); + ACE_DEBUG ((LM_DEBUG, "type = ")); + + if (this->token_type () == ACE_Tokens::MUTEX) + ACE_DEBUG ((LM_DEBUG, "MUTEX\n")); + else // == ACE_Tokens::RWLOCK + { + if (this->proxy_type () == ACE_RW_Token::READER) + ACE_DEBUG ((LM_DEBUG, "RLOCK\n")); + else // == WRITER + ACE_DEBUG ((LM_DEBUG, "WLOCK\n")); + } + + ACE_DEBUG ((LM_DEBUG, "operation = ")); + switch (this->operation_type ()) + { + case ACE_Token_Request::ACQUIRE: + ACE_DEBUG ((LM_DEBUG, "ACQUIRE\n")); + break; + case ACE_Token_Request::RELEASE: + ACE_DEBUG ((LM_DEBUG, "RELEASE\n")); + break; + case ACE_Token_Request::RENEW: + ACE_DEBUG ((LM_DEBUG, "RENEW\n")); + break; + default: + ACE_DEBUG ((LM_DEBUG, "<unknown operation type> = %d\n", this->operation_type ())); + break; + } + + if (this->options ()[ACE_Synch_Options::USE_TIMEOUT] == 0) + ACE_DEBUG ((LM_DEBUG, "blocking forever\n")); + else + { + ACE_DEBUG ((LM_DEBUG, "waiting for %ld secs and %ld usecs\n", + this->options ().timeout ().sec (), this->options ().timeout ().usec ())); + } + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +// Create a ACE_Token_Reply message. + +ACE_Token_Reply::ACE_Token_Reply (void) // Type of reply. +{ + this->arg (0); + this->errnum (0); + this->length (sizeof (Transfer)); +} + +// Encode the transfer buffer into network byte order +// so that it can be sent to the client. + +int +ACE_Token_Reply::encode (void *&buf) +{ + buf = (void *) &this->transfer_; + return this->length (); +} + +// Decode the transfer buffer into host byte order +// so that it can be used by the client. + +int +ACE_Token_Reply::decode (void) +{ + return 0; +} + +// Print out current values of the ACE_Token_Reply object. + +void +ACE_Token_Reply::dump (void) const +{ + ACE_DEBUG ((LM_DEBUG, "*******\nlength = %d\nerrnum = %d", + this->length (), this->errnum ())); + ACE_DEBUG ((LM_DEBUG, "arg = %d", this->arg ())); +} + diff --git a/ace/Token_Request_Reply.h b/ace/Token_Request_Reply.h new file mode 100644 index 00000000000..526a308e1e5 --- /dev/null +++ b/ace/Token_Request_Reply.h @@ -0,0 +1,230 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// Token_Request_Reply.h +// +// = DESCRIPTION +// Define the format used to exchange messages between the +// ACE_Token Server and its clients. +// +// = AUTHOR +// Douglas C. Schmidt (schmidt@cs.wustl.edu) +// Tim Harrison (harrison@cs.wustl.edu) +// +// ============================================================================ + +#if !defined (_TOKEN_REQUEST_REPLY_H) +#define _TOKEN_REQUEST_REPLY_H + +#include "ace/Local_Tokens.h" +#include "ace/Time_Value.h" + +class ACE_Export ACE_Token_Request + // = TITLE + // Message format for delivering requests to the ACE_Token Server. + // + // = DESCRIPTION + // This class is implemented to minimize data copying. + // In particular, all marshaling is done in situ... +{ +public: + enum OPERATION + { + // Operation types. + ACQUIRE, // Acquire the token. + RELEASE, // Release the token. + RENEW, // Renew the token. + REMOVE, // Remove the token. + TRY_ACQUIRE + }; + + ACE_Token_Request (void); + // Default constructor. + + ACE_Token_Request (int token_type, + int proxy_type, + ACE_UINT32 operation, + const char token_name[], + const char client_id[], + const ACE_Synch_Options &options); + // token_type - MUTEX, RWLOCK + // proxy_type - MUTEX, RLOCK, WLOCK (acquires mean different things) + // operation - method + // token_name + // client_id + // options - we check USE_TIMEOUT and use the arg. + + // = Set/get the length of the encoded/decoded message. + ACE_UINT32 length (void) const; + void length (ACE_UINT32); + + // = Set/get the type of proxy + int proxy_type (void) const; + void proxy_type (int proxy_type); + + // = Set/get the type of token + int token_type (void) const; + void token_type (int token_type); + + // = Set/get the type of the operation. + ACE_UINT32 operation_type (void) const; + void operation_type (ACE_UINT32); + + // = Set/get the requeue position. These should be used when renew + // is the operation type. + ACE_UINT32 requeue_position (void) const; + void requeue_position (ACE_UINT32); + + // = Set/get notify. These should be used when acquire is the operation type. + ACE_UINT32 notify (void) const; + void notify (ACE_UINT32); + + // = Set/get the timeout. + ACE_Synch_Options &options (void) const; + void options (const ACE_Synch_Options &options); + + // = Set/get the name of the token and the client id. The set + // method is combined to make it easier on us. We're copying the + // names as a contiguous buffer. + char *token_name (void) const; + char *client_id (void) const; + void token_name (const char *token_name, const char* client_id); + + int encode (void *&); + // Encode the message before transmission. + + int decode (void); + // Decode message after reception. This must be called to set the + // internal options. + + void dump (void) const; + // Print out the values of the message for debugging purposes. + +private: + // = The 5 fields in the <Transfer> struct are transmitted to the server. + // The remaining 2 fields are not tranferred -- they are used only on + // the server-side to simplify lookups. + + struct Transfer + { + ACE_UINT32 length_; + // Length of entire request. + + ACE_UINT32 token_type_; + // Type of the request (i.e., MUTEX, RLOCK, WLOCK... + + ACE_UINT32 proxy_type_; + // Type of the request (i.e., MUTEX, RLOCK, WLOCK... + + ACE_UINT32 operation_type_; + // Type of the request (i.e., <ACQUIRE>, <RELEASE>, <RENEW>, and <REMOVE>). + + ACE_UINT32 requeue_position_; + // this only makes sense when operation type is renew + + ACE_UINT32 notify_; + // this only makes sense when operation type is renew + + // = ACE_Synch_Options stuff + + ACE_UINT32 use_timeout_; + // Indicates if we should block forever. If 1, then <secTimeout_> + // and <usecTimeout_> indicates how long we should wait. If 0, + // then we block forever. + + ACE_UINT32 sec_; + // Max seconds willing to wait for token if not blocking forever. + + ACE_UINT32 usec_; + // Max micro seconds to wait for token if not blocking forever. + + ACE_UINT32 arg_; + // value returned in Token_Reply::arg (); + + char data_[ACE_MAXTOKENNAMELEN + ACE_MAXCLIENTIDLEN + 1]; + // The data portion contains the <tokenName_> followed by a ':' + // followed by the <clientId_>. + } transfer_; + + char *token_name_; + // Pointer to the beginning of the token name in this->data_. + + char *client_id_; + // Pointer to the beginning of the client id in this->data_; + + ACE_Synch_Options options_; + // Holds arg, sec, usec, etc. +}; + +class ACE_Export ACE_Token_Reply + // = TITLE + // Message format for delivering replies from the ACE_Token Server. + // + // = DESCRIPTION + // This class is implemented to minimize data copying. + // In particular, all marshaling is done in situ... +{ +public: + enum Constants + { + SUCCESS = 0 // this MUST be zero!!! + }; + + ACE_Token_Reply (void); + // Default constructor. + + // = Set/get the length of the encoded/decoded message. + ACE_UINT32 length (void) const; + void length (ACE_UINT32); + + // = Set/get the errno of a reply. + ACE_UINT32 errnum (void) const; + void errnum (ACE_UINT32); + + // = Set/get the arg of a reply. + ACE_UINT32 arg (void) const; + void arg (ACE_UINT32); + + int encode (void *&); + // Encode the message before transfer. + + int decode (void); + // Decode a message after reception. + + void dump (void) const; + // Print out the values of the message for debugging purposes. + +private: + // = The 2 fields in the <Transfer> struct are transmitted to the server. + + struct Transfer + { + ACE_UINT32 length_; + // Length of entire reply. + + ACE_UINT32 errno_; + // Indicates why error occurred if <this->type_> == <FAILURE>. + // Typical reasons include: + // <EWOULDBLOCK> (if client requested a non-blocking check for the token). + // <ETIME> (if the client timed out after waiting for the token). + // <ENOLCK> (if the token lock was removed out from underneath a waiter). + // <EACCES> (attempt to renew a token that isn't owned by the client). + + ACE_UINT32 arg_; + // magic cookie + + } transfer_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Token_Request_Reply.i" +#endif /* __ACE_INLINE__ */ + +#endif /* _TOKEN_REQUEST_REPLY_H */ diff --git a/ace/Token_Request_Reply.i b/ace/Token_Request_Reply.i new file mode 100644 index 00000000000..66428003359 --- /dev/null +++ b/ace/Token_Request_Reply.i @@ -0,0 +1,190 @@ +/* -*- C++ -*- */ +// $Id$ + +// Token_Request_Reply.i + +// = Set/get the length of the encoded/decoded message. + +ACE_INLINE ACE_UINT32 +ACE_Token_Request::length (void) const +{ + return ntohl (this->transfer_.length_); +} + +ACE_INLINE void +ACE_Token_Request::length (ACE_UINT32 l) +{ + this->transfer_.length_ = htonl (l); +} + +// = Set/get the type of the message. +ACE_INLINE int +ACE_Token_Request::token_type (void) const +{ + return (int) ntohl (this->transfer_.token_type_); +} + +ACE_INLINE void +ACE_Token_Request::token_type (int t) +{ + this->transfer_.token_type_ = htonl ((ACE_UINT32) t); +} + +// = Set/get the type of the message. +ACE_INLINE int +ACE_Token_Request::proxy_type (void) const +{ + return (int) ntohl (this->transfer_.proxy_type_); +} + +ACE_INLINE void +ACE_Token_Request::proxy_type (int t) +{ + this->transfer_.proxy_type_ = htonl ((ACE_UINT32) t); +} + +// = Set/get the type of the message. +ACE_INLINE ACE_UINT32 +ACE_Token_Request::operation_type (void) const +{ + return ntohl (this->transfer_.operation_type_); +} + +ACE_INLINE void +ACE_Token_Request::operation_type (ACE_UINT32 t) +{ + this->transfer_.operation_type_ = htonl (t); +} + +// = Set/get the requeue position +ACE_INLINE ACE_UINT32 +ACE_Token_Request::requeue_position (void) const +{ + return ntohl (this->transfer_.requeue_position_); +} + +ACE_INLINE void +ACE_Token_Request::requeue_position (ACE_UINT32 rq) +{ + this->transfer_.requeue_position_ = htonl (rq); +} + +// = Set/get the requeue position +ACE_INLINE ACE_UINT32 +ACE_Token_Request::notify (void) const +{ + return ntohl (this->transfer_.notify_); +} + +ACE_INLINE void +ACE_Token_Request::notify (ACE_UINT32 rq) +{ + this->transfer_.notify_ = htonl (rq); +} + +// = Set/get the blocking semantics. +ACE_INLINE ACE_Synch_Options & +ACE_Token_Request::options (void) const +{ + return (ACE_Synch_Options &) options_; +} + +ACE_INLINE void +ACE_Token_Request::options (const ACE_Synch_Options &opt) +{ + // fight the friggin const from hell + ACE_Synch_Options *options = (ACE_Synch_Options *) &opt; + + transfer_.use_timeout_ = options->operator[](ACE_Synch_Options::USE_TIMEOUT); + if (transfer_.use_timeout_ == 1) + { + transfer_.usec_ = options->timeout ().usec (); + transfer_.sec_ = options->timeout ().sec (); + } + else + { + transfer_.usec_ = 0; + transfer_.sec_ = 0; + } +} + +// = Set/get the name of the token. +ACE_INLINE char * +ACE_Token_Request::token_name (void) const +{ + return token_name_; +} + +ACE_INLINE void +ACE_Token_Request::token_name (const char *token_name, const char *client_id) +{ + size_t token_name_length = ACE_OS::strlen (token_name) + 1; // Add 1 for '\0'. + size_t client_id_length = ACE_OS::strlen (client_id) + 1; // Add 1 for '\0'. + + // Set up pointers and copy token_name and client_id into request. + token_name_ = this->transfer_.data_; + client_id_ = &this->token_name_[token_name_length + 1]; // Add 1 for ':'; + client_id_[-1] = ':'; // Insert the ':' before this->clientId_. + + (void) ACE_OS::memcpy (token_name_, token_name, token_name_length); + (void) ACE_OS::memcpy (client_id_, client_id, client_id_length); + + // Compute size of the fixed portion of the message... + size_t len = sizeof this->transfer_ - sizeof this->transfer_.data_; + + // ... then add in the amount of the variable-sized portion. + len += token_name_length + client_id_length + 1; + + this->length (len); +} + +// = Set/get the id of the client. +ACE_INLINE char * +ACE_Token_Request::client_id (void) const +{ + return this->client_id_; +} + +// ************************************************************ +// ************************************************************ +// ************************************************************ + +// = Set/get the length of the encoded/decoded message. +ACE_INLINE ACE_UINT32 +ACE_Token_Reply::length (void) const +{ + return ntohl (this->transfer_.length_); +} + +ACE_INLINE void +ACE_Token_Reply::length (ACE_UINT32 l) +{ + this->transfer_.length_ = htonl (l); +} + +// = Set/get the errno of a failed reply. +ACE_INLINE ACE_UINT32 +ACE_Token_Reply::errnum (void) const +{ + return ntohl (this->transfer_.errno_); +} + +ACE_INLINE void +ACE_Token_Reply::errnum (ACE_UINT32 e) +{ + this->transfer_.errno_ = htonl (e); +} + +// = Set/get the length of the encoded/decoded message. +ACE_INLINE ACE_UINT32 +ACE_Token_Reply::arg (void) const +{ + return ntohl (this->transfer_.arg_); +} + +ACE_INLINE void +ACE_Token_Reply::arg (ACE_UINT32 arg) +{ + this->transfer_.arg_ = htonl (arg); +} + diff --git a/ace/Trace.cpp b/ace/Trace.cpp new file mode 100644 index 00000000000..1053a45159f --- /dev/null +++ b/ace/Trace.cpp @@ -0,0 +1,115 @@ +// Trace.cpp +// $Id$ + +// We need this to get the status of ACE_NTRACE... + +#define ACE_BUILD_DLL +#include "ace/config.h" + +// Turn off tracing for the duration of this file. +#if defined (ACE_NTRACE) +#undef ACE_NTRACE +#endif /* ACE_NTRACE */ +#define ACE_NTRACE 1 + +// This must come first to avoid "order of include" problems... + +#if !defined (ACE_HAS_INLINED_OSCALLS) && !defined (ACE_WIN32) +#define ACE_HAS_INLINED_OSCALLS +#include "ace/ACE.h" +#undef ACE_HAS_INLINED_OSCALLS +#else +#include "ace/ACE.h" +#endif /* !ACE_HAS_INLINED_OSCALLS */ + +#include "ace/Log_Msg.h" + +#include "ace/Trace.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Trace.i" +#endif /* __ACE_INLINE__ */ + +// = Static initialization. + +// Keeps track of how far to indent per trace call. +int ACE_Trace::nesting_indent_ = ACE_Trace::DEFAULT_INDENT; + +// Is tracing enabled? +int ACE_Trace::enable_tracing_ = ACE_Trace::DEFAULT_TRACING; + +ACE_ALLOC_HOOK_DEFINE(ACE_Trace) + +void +ACE_Trace::dump (void) const +{ +} + +// Enable the tracing facility. + +void +ACE_Trace::start_tracing (void) +{ + ACE_Trace::enable_tracing_ = 1; +} + +// Disable the tracing facility. + +void +ACE_Trace::stop_tracing (void) +{ + ACE_Trace::enable_tracing_ = 0; +} + +// Change the nesting indentation level. + +void +ACE_Trace::set_nesting_indent (int indent) +{ + ACE_Trace::nesting_indent_ = indent; +} + +// Perform the first part of the trace, which prints out the string N, +// the LINE, and the ACE_FILE as the function is entered. + +ACE_Trace::ACE_Trace (const char *n, + int line, + const char *file) +{ + this->name_ = n; + + if (ACE_Trace::enable_tracing_) + { + ACE_Log_Msg *lm = ACE_LOG_MSG; + if (lm->tracing_enabled () + && lm->trace_active () == 0) + { + lm->trace_active (1); + ACE_DEBUG ((LM_DEBUG, "%*s(%t) calling %s in file `%s' on line %d\n", + ACE_Trace::nesting_indent_ * lm->inc (), + "", this->name_, file, line)); + lm->trace_active (0); + } + } +} + +// Perform the second part of the trace, which prints out the NAME as +// the function is exited. + +ACE_Trace::~ACE_Trace (void) +{ + if (ACE_Trace::enable_tracing_) + { + ACE_Log_Msg *lm = ACE_LOG_MSG; + if (lm->tracing_enabled () + && lm->trace_active () == 0) + { + lm->trace_active (1); + ACE_DEBUG ((LM_DEBUG, "%*s(%t) leaving %s\n", + ACE_Trace::nesting_indent_ * lm->dec (), + "", this->name_)); + lm->trace_active (0); + } + } +} + diff --git a/ace/Trace.h b/ace/Trace.h new file mode 100644 index 00000000000..8943b7a8055 --- /dev/null +++ b/ace/Trace.h @@ -0,0 +1,77 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Trace.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TRACE_H) +#define ACE_TRACE_H + +class ACE_Export ACE_Trace + // = TITLE + // A C++ trace facility that keeps track of which methods are + // entered and exited. + // + // = DESCRIPTION + // This class uses C++ constructors and destructors to automate + // the ACE_Trace nesting. In addition, thread-specific storage + // is used to enable multiple threads to work correctly. +{ +public: + // = Initialization and termination methods. + + ACE_Trace (const char *n, int line = 0, const char *file = ""); + // Perform the first part of the trace, which prints out the string + // N, the LINE, and the ACE_FILE as the function is entered. + + ~ACE_Trace (void); + // Perform the second part of the trace, which prints out the NAME + // as the function is exited. + + // = Control the tracing level. + static void start_tracing (void); + // Enable the tracing facility. + + static void stop_tracing (void); + // Disable the tracing facility. + + static void set_nesting_indent (int indent); + // Change the nesting indentation level. + + void dump (void) const; + // Dump the state of an object. + +private: + // Keeps track of how deeply the call stack is nested (this is + // maintained in thread-specific storage to ensure correctness in + // multiple threads of control. + + const char *name_; + // Name of the method we are in. + + static int nesting_indent_; + // Keeps track of how far to indent per trace call. + + static int enable_tracing_; + // Is tracing enabled? + + // Default values. + enum + { + DEFAULT_INDENT = 3, + DEFAULT_TRACING = 1 + }; +}; + +#endif /* ACE_TRACE_H */ diff --git a/ace/Trace.i b/ace/Trace.i new file mode 100644 index 00000000000..a480d9af351 --- /dev/null +++ b/ace/Trace.i @@ -0,0 +1,7 @@ +/* -*- C++ -*- */ +// $Id$ + +// Trace.i + + + diff --git a/ace/Typed_SV_Message.cpp b/ace/Typed_SV_Message.cpp new file mode 100644 index 00000000000..29e227b43c5 --- /dev/null +++ b/ace/Typed_SV_Message.cpp @@ -0,0 +1,21 @@ +// Typed_SV_Message.cpp +// $Id$ + +#if !defined (ACE_TYPED_SV_MESSAGE_C) +#define ACE_TYPED_SV_MESSAGE_C +#define ACE_BUILD_DLL +#include "ace/Typed_SV_Message.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Typed_SV_Message.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Typed_SV_Message) + +template <class T> void +ACE_Typed_SV_Message<T>::dump (void) const +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::dump"); +} + +#endif /* ACE_TYPED_SV_MESSAGE_C */ diff --git a/ace/Typed_SV_Message.h b/ace/Typed_SV_Message.h new file mode 100644 index 00000000000..08e5ffc70dc --- /dev/null +++ b/ace/Typed_SV_Message.h @@ -0,0 +1,88 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Typed_SV_Message.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TYPED_SV_MESSAGE_H) +#define ACE_TYPED_SV_MESSAGE_H + +#include "ace/ACE.h" + +template <class T> +class ACE_Typed_SV_Message + // = TITLE + // Defines the header file for the C++ wrapper for System V + // message queues. +{ +public: + // = Initialization and termination methods. + ACE_Typed_SV_Message (long type = 0, + int length = sizeof (T), + int max_size = sizeof (T)); + ACE_Typed_SV_Message (const T &data, + long type = 0, + int length = sizeof (T), + int max_size = sizeof (T)); + ~ACE_Typed_SV_Message (void); + + // = Get/set the type of the message. + long type (void) const; + void type (long type); + + // = Get/set the length of the message. + int length (void) const; + void length (int l); + + // = Get/set the maximum size of the message. + int max_size (void) const; + void max_size (int m); + + // = Get/set a pointer to the data in the message. + T &data (void); + void data (const T &data); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + long type_; + // Type of message. + + int length_; + // Length of this message. + + int max_; + // Maximum length of any message. + + T data_; + // Data stored in a message. +}; + +#if defined (__ACE_INLINE__) +#include "ace/Typed_SV_Message.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Typed_SV_Message.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Typed_SV_Message.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_TYPED_SV_MESSAGE_H */ diff --git a/ace/Typed_SV_Message.i b/ace/Typed_SV_Message.i new file mode 100644 index 00000000000..5717dcc2d50 --- /dev/null +++ b/ace/Typed_SV_Message.i @@ -0,0 +1,91 @@ +/* -*- C++ -*- */ +// $Id$ + +// Typed_SV_Message.i + +template <class T> ACE_INLINE +ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message (long t, + int l, + int m) + : type_ (t) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message"); + this->length (l); + this->max_size (m); +} + +template <class T> ACE_INLINE +ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message (const T &d, + long t, + int l, + int m) + : data_ (d), + type_ (t) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::ACE_Typed_SV_Message"); + this->length (l); + this->max_size (m); +} + +template <class T> ACE_INLINE +ACE_Typed_SV_Message<T>::~ACE_Typed_SV_Message (void) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::~ACE_Typed_SV_Message"); +} + +template <class T> ACE_INLINE long +ACE_Typed_SV_Message<T>::type (void) const +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::type"); + return this->type_; +} + +template <class T> ACE_INLINE void +ACE_Typed_SV_Message<T>::type (long t) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::type"); + this->type_ = t; +} + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message<T>::length (void) const +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::length"); + return this->length_; +} + +template <class T> ACE_INLINE void +ACE_Typed_SV_Message<T>::length (int len) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::length"); + this->length_ = len + (sizeof *this - (sizeof this->type_ + sizeof this->data_)); +} + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message<T>::max_size (void) const +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::max_size"); + return this->max_; +} + +template <class T> ACE_INLINE void +ACE_Typed_SV_Message<T>::max_size (int m) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::max_size"); + this->max_ = m + (sizeof *this - (sizeof this->type_ + sizeof this->data_)); +} + +template <class T> T & +ACE_Typed_SV_Message<T>::data (void) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::data"); + return this->data_; +} + +template <class T> void +ACE_Typed_SV_Message<T>::data (const T &d) +{ + ACE_TRACE ("ACE_Typed_SV_Message<T>::data"); + this->data_ = d; +} + diff --git a/ace/Typed_SV_Message_Queue.cpp b/ace/Typed_SV_Message_Queue.cpp new file mode 100644 index 00000000000..b77f07de62e --- /dev/null +++ b/ace/Typed_SV_Message_Queue.cpp @@ -0,0 +1,46 @@ +// Typed_SV_Message_Queue.cpp +// $Id$ + +#if !defined (ACE_TYPED_SV_MESSAGE_QUEUE_C) +#define ACE_TYPED_SV_MESSAGE_QUEUE_C + +#define ACE_BUILD_DLL +#include "ace/Typed_SV_Message.h" +#include "ace/Typed_SV_Message_Queue.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Typed_SV_Message_Queue.i" +#endif /* __ACE_INLINE__ */ + +ACE_ALLOC_HOOK_DEFINE(ACE_Typed_SV_Message_Queue) + +template <class T> void +ACE_Typed_SV_Message_Queue<T>::dump (void) const +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::dump"); +} + +template <class T> +ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue (void) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue"); +} + +template <class T> +ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue (key_t external_id, + int create, + int perms) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::ACE_Typed_SV_Message_Queue"); + if (this->open (external_id, create, perms) == -1) + ACE_ERROR ((LM_ERROR, + "ACE_Typed_SV_Message_Queue::ACE_Typed_SV_Message_Queue")); +} + +template <class T> +ACE_Typed_SV_Message_Queue<T>::~ACE_Typed_SV_Message_Queue (void) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::~ACE_Typed_SV_Message_Queue"); +} + +#endif /* ACE_TYPED_SV_MESSAGE_QUEUE_C */ diff --git a/ace/Typed_SV_Message_Queue.h b/ace/Typed_SV_Message_Queue.h new file mode 100644 index 00000000000..40b4f36cfee --- /dev/null +++ b/ace/Typed_SV_Message_Queue.h @@ -0,0 +1,78 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Typed_SV_Message_Queue.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_TYPED_MESSAGE_QUEUE_H) +#define ACE_TYPED_MESSAGE_QUEUE_H + +#include "ace/SV_Message_Queue.h" +#include "ace/Typed_SV_Message.h" + +template <class T> +class ACE_Typed_SV_Message_Queue + // = TITLE + // Defines the header file for the C++ wrapper for message queues. +{ +public: + enum + { + ACE_CREATE = IPC_CREAT, + ACE_OPEN = 0, + ACE_NOWAIT = IPC_NOWAIT + }; + + // = Initialization and termination operations. + ACE_Typed_SV_Message_Queue (void); + ACE_Typed_SV_Message_Queue (key_t external_id, + int create = ACE_OPEN, + int perms = ACE_DEFAULT_PERMS); + int open (key_t external_id, + int create = ACE_OPEN, + int perms = ACE_DEFAULT_PERMS); + int close (void); + int remove (void); + ~ACE_Typed_SV_Message_Queue (void); + + // = Send and recv methods. + int send (const ACE_Typed_SV_Message<T> &mb, int mflags = 0); + int recv (ACE_Typed_SV_Message<T> &mb, int mflags = 0); + + int control (int option, void *arg = 0); + // Control the underlying message queue. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_SV_Message_Queue message_queue_; +}; + +#if defined (__ACE_INLINE__) +#include "ace/Typed_SV_Message_Queue.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Typed_SV_Message_Queue.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Typed_SV_Message_Queue.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_TYPED_MESSAGE_QUEUE_H */ diff --git a/ace/Typed_SV_Message_Queue.i b/ace/Typed_SV_Message_Queue.i new file mode 100644 index 00000000000..9dcbb07075c --- /dev/null +++ b/ace/Typed_SV_Message_Queue.i @@ -0,0 +1,63 @@ +/* -*- C++ -*- */ +// $Id$ + +// Typed_SV_Message_Queue.i + +#include "ace/SV_Message_Queue.h" +#include "ace/Log_Msg.h" + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message_Queue<T>::open (key_t external_id, + int create, + int perms) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::open"); + return this->message_queue_.open (external_id, create, perms); +} + +/* What does it mean to close a message queue?! */ + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message_Queue<T>::close (void) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::close"); + return 1; +} + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message_Queue<T>::recv (ACE_Typed_SV_Message<T> &mb, + int mflags) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::recv"); + int length = this->message_queue_.recv ((ACE_SV_Message &) mb, + mb.max_size (), mb.type (), mflags); + + if (length != -1) + mb.length (length); + + return length; +} + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message_Queue<T>::send (const ACE_Typed_SV_Message<T> &mb, + int mflags) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::send"); + return this->message_queue_.send ((ACE_SV_Message &) mb, + mb.length (), mflags); +} + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message_Queue<T>::remove (void) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::remove"); + return this->message_queue_.remove (); +} + +template <class T> ACE_INLINE int +ACE_Typed_SV_Message_Queue<T>::control (int option, + void *arg) +{ + ACE_TRACE ("ACE_Typed_SV_Message_Queue<T>::control"); + return this->message_queue_.control (option, arg); +} diff --git a/ace/UNIX_Addr.cpp b/ace/UNIX_Addr.cpp new file mode 100644 index 00000000000..fdabb40c219 --- /dev/null +++ b/ace/UNIX_Addr.cpp @@ -0,0 +1,104 @@ +// UNIX_Addr.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/UNIX_Addr.h" + +#if !defined (__ACE_INLINE__) +#include "ace/UNIX_Addr.i" +#endif /* __ACE_INLINE__ */ + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +ACE_ALLOC_HOOK_DEFINE(ACE_UNIX_Addr) + +// Set a pointer to the address. +void +ACE_UNIX_Addr::set_addr (void *addr, int len) +{ + ACE_TRACE ("ACE_UNIX_Addr::set_addr"); + + this->ACE_Addr::base_set (AF_UNIX, len); + ACE_OS::memcpy ((void *) &this->unix_addr_, + (void *) addr, + len); +} + +void +ACE_UNIX_Addr::dump (void) const +{ +} + +// Do nothing constructor. + +ACE_UNIX_Addr::ACE_UNIX_Addr (void) + : ACE_Addr (AF_UNIX, sizeof this->unix_addr_) +{ + (void) ACE_OS::memset ((void *) &this->unix_addr_, 0, sizeof this->unix_addr_); +} + +// Copy constructor. + +ACE_UNIX_Addr::ACE_UNIX_Addr (const ACE_UNIX_Addr &sa) + : ACE_Addr (AF_UNIX, sa.get_size ()) +{ + size_t size = sa.get_size (); + + // Add one extra byte to account for the NUL at the end of the + // pathname. + if (size < sizeof this->unix_addr_) + size = sa.get_size () + 1; + + this->unix_addr_.sun_family = AF_UNIX; + ACE_OS::strcpy (this->unix_addr_.sun_path, sa.unix_addr_.sun_path); +} + +void +ACE_UNIX_Addr::set (const sockaddr_un *un, int len) +{ + (void) ACE_OS::memset ((void *) &this->unix_addr_, 0, + sizeof this->unix_addr_); + this->unix_addr_.sun_family = AF_UNIX; + ACE_OS::strcpy (this->unix_addr_.sun_path, un->sun_path); + this->base_set (AF_UNIX, len); +} + +ACE_UNIX_Addr::ACE_UNIX_Addr (const sockaddr_un *un, int len) +{ + this->set (un, len); +} + +void +ACE_UNIX_Addr::set (const char rendezvous_point[]) +{ + (void) ACE_OS::memset ((void *) &this->unix_addr_, 0, + sizeof this->unix_addr_); + int len = ACE_OS::strlen (rendezvous_point); + + this->unix_addr_.sun_family = AF_UNIX; + + if (len >= sizeof this->unix_addr_.sun_path) + { + /* At this point, things are screwed up, so let's make sure we + don't crash. */ + (void) ACE_OS::strncpy (this->unix_addr_.sun_path, + rendezvous_point, + sizeof this->unix_addr_.sun_path); + len = sizeof this->unix_addr_.sun_path; + this->unix_addr_.sun_path[len - 1] = '\0'; + // Don't count the NUL byte at the end of the string. + len -= 2; + } + else + (void) ACE_OS::strcpy (this->unix_addr_.sun_path, rendezvous_point); + this->ACE_Addr::base_set (AF_UNIX, len + sizeof this->unix_addr_.sun_family); +} + +// Create a ACE_Addr from a UNIX pathname. + +ACE_UNIX_Addr::ACE_UNIX_Addr (const char rendezvous_point[]) +{ + this->set (rendezvous_point); +} + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/UNIX_Addr.h b/ace/UNIX_Addr.h new file mode 100644 index 00000000000..07d7874ebff --- /dev/null +++ b/ace/UNIX_Addr.h @@ -0,0 +1,85 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// UNIX_Addr.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_UNIX_ADDR_H) +#define ACE_UNIX_ADDR_H +#include "ace/Addr.h" + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +class ACE_Export ACE_UNIX_Addr : public ACE_Addr + // = TITLE + // Defines the ``UNIX domain address family'' address format. +{ +public: + // = Initialization methods. + ACE_UNIX_Addr (void); + // Default constructor. + + ACE_UNIX_Addr (const ACE_UNIX_Addr &sa); + // Copy constructor. + + ACE_UNIX_Addr (const char rendezvous_point[]); + // Creates an ACE_UNIX_Addr from a string. + + ACE_UNIX_Addr (const sockaddr_un *, int len); + // Creates an ACE_INET_Addr from a sockaddr_un structure. + + void set (const char rendezvous_point[]); + // Creates an ACE_UNIX_Addr from a string. + + void set (const sockaddr_un *, int len); + // Creates an ACE_INET_Addr from a sockaddr_un structure. + + virtual void *get_addr (void) const; + // Return a pointer to the underlying network address. + + virtual void set_addr (void *addr, int len); + // Set a pointer to the underlying network address. + + virtual int addr_to_string (char addr[], size_t) const; + // Transform the current address into string format. + + virtual int string_to_addr (const char addr[]); + // Transform the string into the current addressing format. + + virtual int operator == (const ACE_Addr &SAP) const; + // Compare two addresses for equality. + + virtual int operator != (const ACE_Addr &SAP) const; + // Compare two addresses for inequality. + + const char *get_path_name (void) const; + // Return the path name of the underlying rendezvous point. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + sockaddr_un unix_addr_; + // Underlying socket address. +}; + +#if defined (__ACE_INLINE__) +#include "ace/UNIX_Addr.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ +#endif /* ACE_UNIX_ADDR_H */ diff --git a/ace/UNIX_Addr.i b/ace/UNIX_Addr.i new file mode 100644 index 00000000000..88fcc688cc5 --- /dev/null +++ b/ace/UNIX_Addr.i @@ -0,0 +1,61 @@ +/* -*- C++ -*- */ +// $Id$ + +// UNIX_Addr.i + +#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) + +// Return a pointer to the underlying address. + +ACE_INLINE void * +ACE_UNIX_Addr::get_addr (void) const +{ + return (void *) &this->unix_addr_; +} + +// Transform the string into the current addressing format. + +ACE_INLINE int +ACE_UNIX_Addr::string_to_addr (const char addr[]) +{ + ACE_OS::strncpy (this->unix_addr_.sun_path, addr, + sizeof this->unix_addr_.sun_path); + return 0; +} + +// Transform the current address into string format. + +ACE_INLINE int +ACE_UNIX_Addr::addr_to_string (char s[], size_t len) const +{ + ACE_OS::strncpy (s, this->unix_addr_.sun_path, len); + return 0; +} + +// Compare two addresses for equality. + +ACE_INLINE int +ACE_UNIX_Addr::operator == (const ACE_Addr &sap) const +{ + return ACE_OS::strncmp (this->unix_addr_.sun_path, + ((const ACE_UNIX_Addr &) sap).unix_addr_.sun_path, + sizeof this->unix_addr_.sun_path) == 0; +} + +// Compare two addresses for inequality. + +ACE_INLINE int +ACE_UNIX_Addr::operator != (const ACE_Addr &sap) const +{ + return !((*this) == sap); // This is lazy, of course... ;-) +} + +// Return the path name used for the rendezvous point. + +ACE_INLINE const char * +ACE_UNIX_Addr::get_path_name (void) const +{ + return this->unix_addr_.sun_path; +} + +#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ diff --git a/ace/UPIPE_Acceptor.cpp b/ace/UPIPE_Acceptor.cpp new file mode 100644 index 00000000000..9d3f97fcb77 --- /dev/null +++ b/ace/UPIPE_Acceptor.cpp @@ -0,0 +1,115 @@ +// UPIPE_Acceptor.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/UPIPE_Acceptor.h" +#include "ace/Log_Msg.h" + +#if defined (ACE_HAS_THREADS) + +ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Acceptor) + +void +ACE_UPIPE_Acceptor::dump (void) const +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::dump"); +} + +/* Do nothing routine for constructor. */ + +ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor (void) + : mb_ (sizeof (ACE_UPIPE_Stream *)) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor"); +} + +ACE_UPIPE_Acceptor::~ACE_UPIPE_Acceptor (void) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::~ACE_UPIPE_Acceptor"); +} + +// General purpose routine for performing server ACE_UPIPE. + +int +ACE_UPIPE_Acceptor::open (const ACE_UPIPE_Addr &local_addr, + int reuse_addr) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::open"); + return this->ACE_SPIPE_Acceptor::open (local_addr, reuse_addr); +} + +int +ACE_UPIPE_Acceptor::close (void) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::close"); + return this->ACE_SPIPE_Acceptor::close (); +} + +// General purpose routine for accepting new connections. + +ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor (const ACE_UPIPE_Addr &local_addr, + int reuse_addr) + : mb_ (sizeof (ACE_UPIPE_Stream *)) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::ACE_UPIPE_Acceptor"); + + if (this->open (local_addr, reuse_addr) == -1) + ACE_ERROR ( (LM_ERROR, "%p\n", "ACE_UPIPE_Acceptor")); +} + +int +ACE_UPIPE_Acceptor::accept (ACE_UPIPE_Stream &new_stream, + ACE_UPIPE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::accept"); + ACE_SPIPE_Stream new_io; + + if (this->ACE_SPIPE_Acceptor::accept (new_io, remote_addr, + timeout, restart) == -1) + return -1; + else + { + ACE_UPIPE_Stream *remote_stream = 0; + // Transfer address ownership. + new_stream.set_handle (new_io.get_handle ()); + + new_io.get_local_addr (new_stream.local_addr_); + new_io.get_remote_addr (new_stream.remote_addr_); + + // Now that we got the fd, we'll read the address of the + // connector-side ACE_UPIPE_Stream out of the pipe and link that + // ACE_UPIPE_Stream to our ACE_UPIPE_Stream + + if (ACE_OS::read (new_stream.get_handle (), + (char *) &remote_stream, + sizeof remote_stream) == -1) + ACE_ERROR ((LM_ERROR, + "ACE_UPIPE_Acceptor: %p\n", + "read stream address failed")); + else if (new_stream.stream_.link (remote_stream->stream_) == -1) + ACE_ERROR ((LM_ERROR, + "ACE_UPIPE_Acceptor: %p\n", + "link streams failed")); + // Send a message over the new streampipe to confirm acceptance. + else if (new_stream.send (&mb_, 0) == -1) + ACE_ERROR ((LM_ERROR, + "ACE_UPIPE_Acceptor: %p\n", + "linked stream.put failed")); + + // Close down the new_stream at this point in order to conserve + // handles. Note that we don't need the SPIPE connection + // anymore since we're now linked via the <Message_Queue>. + new_stream.ACE_SPIPE::close (); + return 0; + } +} + +#endif /* ACE_HAS_THREADS */ + + + + + + diff --git a/ace/UPIPE_Acceptor.h b/ace/UPIPE_Acceptor.h new file mode 100644 index 00000000000..b855285f76e --- /dev/null +++ b/ace/UPIPE_Acceptor.h @@ -0,0 +1,81 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// UPIPE_Acceptor.h +// +// = AUTHOR +// Gerhard Lenzer and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_UPIPE_ACCEPTOR_H) +#define ACE_UPIPE_ACCEPTOR_H + +#include "ace/UPIPE_Stream.h" +#include "ace/Synch.h" +#include "ace/SPIPE_Acceptor.h" +#include "ace/Thread_Manager.h" + +#if defined (ACE_HAS_THREADS) + +class ACE_Export ACE_UPIPE_Acceptor : public ACE_SPIPE_Acceptor + // = TITLE + // Defines the format and interface for the listener side of the + // ACE_UPIPE_Stream. +{ +public: + // = Initialization and termination. + ACE_UPIPE_Acceptor (void); + // Default constructor. + + ACE_UPIPE_Acceptor (const ACE_UPIPE_Addr &local_sap, + int reuse_addr = 0); + // Initialize passive endpoint. + + int open (const ACE_UPIPE_Addr &local_sap, + int reuse_addr = 0); + // Initialize passive endpoint. + + ~ACE_UPIPE_Acceptor (void); + // Close down and release resources. + + int close (void); + // Close down and release resources. + + int remove (void); + // Close down and release resources and remove the underlying SPIPE + // rendezvous point. + + // = Passive connection acceptance method. + int accept (ACE_UPIPE_Stream &server_stream, + ACE_UPIPE_Addr *remote_addr = 0, + ACE_Time_Value *timeout = 0, + int restart = 1); + // Accept a new data transfer connection. A <timeout> of 0 means + // block forever, a <timeout> of {0, 0} means poll. <restart> == 1 + // means "restart if interrupted." + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Thread_Manager tm; + // Manage threads. + + ACE_Message_Block mb_; + // To confirm connection establishment. +}; + +#include "ace/UPIPE_Acceptor.i" +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_UPIPE_ACCEPTOR_H */ diff --git a/ace/UPIPE_Acceptor.i b/ace/UPIPE_Acceptor.i new file mode 100644 index 00000000000..7a395658212 --- /dev/null +++ b/ace/UPIPE_Acceptor.i @@ -0,0 +1,11 @@ +/* -*- C++ -*- */ +// $Id$ + +// UPIPE_Acceptor.i + +inline int +ACE_UPIPE_Acceptor::remove (void) +{ + ACE_TRACE ("ACE_UPIPE_Acceptor::remove"); + return this->ACE_SPIPE_Acceptor::remove (); +} diff --git a/ace/UPIPE_Addr.h b/ace/UPIPE_Addr.h new file mode 100644 index 00000000000..6f86a99547f --- /dev/null +++ b/ace/UPIPE_Addr.h @@ -0,0 +1,25 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// UPIPE_Addr.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#if !defined (ACE_UPIPE_ADDR_H) +#define ACE_UPIPE_ADDR_H + +#include "ace/SPIPE_Addr.h" + +typedef ACE_SPIPE_Addr ACE_UPIPE_Addr; + +#endif /* ACE_UPIPE_ADDR_H */ diff --git a/ace/UPIPE_Connector.cpp b/ace/UPIPE_Connector.cpp new file mode 100644 index 00000000000..e4aad1a28a3 --- /dev/null +++ b/ace/UPIPE_Connector.cpp @@ -0,0 +1,86 @@ +// UPIPE_Connector.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/UPIPE_Connector.h" + +#if defined (ACE_HAS_THREADS) + +ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Connector) + +void +ACE_UPIPE_Connector::dump (void) const +{ + ACE_TRACE ("ACE_UPIPE_Connector::dump"); +} + +ACE_UPIPE_Connector::ACE_UPIPE_Connector (void) +{ + ACE_TRACE ("ACE_UPIPE_Connector::ACE_UPIPE_Connector"); +} + +int +ACE_UPIPE_Connector::connect (ACE_UPIPE_Stream &new_stream, + const ACE_UPIPE_Addr &addr, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_UPIPE_Connector::connect"); + ACE_ASSERT (new_stream.get_handle () == ACE_INVALID_HANDLE); + + ACE_HANDLE handle = ACE::handle_timed_open (timeout, + addr.get_path_name (), + flags, perms); + + if (handle == ACE_INVALID_HANDLE) + return -1; +#if !defined (ACE_WIN32) + else if (ACE_OS::isastream (handle) != 1) + return -1; +#endif + else // We're connected! + { + ACE_UPIPE_Stream *ustream = &new_stream; + + new_stream.set_handle (handle); + new_stream.remote_addr_ = addr; // class copy. + + // Now send the address of our ACE_UPIPE_Stream over this pipe + // to our corresponding ACE_UPIPE_Acceptor, so he may link the + // two streams. + ssize_t result = ACE_OS::write (handle, + (const char *) &ustream, + sizeof ustream); + if (result == -1) + ACE_ERROR ((LM_ERROR, + "ACE_UPIPE_Connector %p\n", + "write to pipe failed")); + + // Wait for confirmation of stream linking. + ACE_Message_Block *mb_p = 0; + + // Our part is done, wait for server to confirm connection. + result = new_stream.recv (mb_p, 0); + + // Do *not* coalesce the following two checks for result == -1. + // They perform different checks and cannot be merged. + if (result == -1) + ACE_ERROR ((LM_ERROR, "ACE_UPIPE_Connector %p\n", + "no confirmation from server")); + + if (result == -1) + this->close (); + else + // Close down the new_stream at this point in order to + // conserve handles. Note that we don't need the SPIPE + // connection anymore since we're linked via the Message_Queue + // now. + new_stream.ACE_SPIPE::close (); + return result; + } +} +#endif /* ACE_HAS_THREADS */ + diff --git a/ace/UPIPE_Connector.h b/ace/UPIPE_Connector.h new file mode 100644 index 00000000000..56fe8cb5b15 --- /dev/null +++ b/ace/UPIPE_Connector.h @@ -0,0 +1,92 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// UPIPE_Connector.h +// +// = AUTHOR +// Gerhard Lenzer and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (ACE_UPIPE_CONNECTOR_H) +#define ACE_UPIPE_CONNECTOR_H + +#include "ace/UPIPE_Stream.h" +#include "ace/Synch.h" +#include "ace/SPIPE_Stream.h" + +#if defined (ACE_HAS_THREADS) + +class ACE_Export ACE_UPIPE_Connector : public ACE_SPIPE + // = TITLE + // Defines an active connection factory for the + // <ACE_UPIPE_STREAM> wrappers. +{ +public: + // = Initialization methods. + ACE_UPIPE_Connector (void); + // Default constructor. + + ACE_UPIPE_Connector (ACE_UPIPE_Stream &new_stream, + const ACE_UPIPE_Addr &addr, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + int connect (ACE_UPIPE_Stream &new_stream, + const ACE_UPIPE_Addr &addr, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = O_RDWR, + int perms = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIMEDOUT>. + // The <local_sap> is the value of local address to bind to. If + // it's the default value of <ACE_Addr::sap_any> then the user is + // letting the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + // The <flags> and <perms> arguments are passed down to the open() + // method. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +}; + +#include "ace/UPIPE_Connector.i" +#endif /* ACE_HAS_THREADS */ +#endif /* ACE_UPIPE_CONNECTOR_H */ diff --git a/ace/UPIPE_Connector.i b/ace/UPIPE_Connector.i new file mode 100644 index 00000000000..5404622af03 --- /dev/null +++ b/ace/UPIPE_Connector.i @@ -0,0 +1,30 @@ +/* -*- C++ -*- */ +// $Id$ + +// UPIPE_Connector.i + +#include "ace/Log_Msg.h" + +// Creates a Local ACE_UPIPE. + +inline +ACE_UPIPE_Connector::ACE_UPIPE_Connector (ACE_UPIPE_Stream &new_stream, + const ACE_UPIPE_Addr &addr, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms) +{ + ACE_TRACE ("ACE_UPIPE_Connector::ACE_UPIPE_Connector"); + if (this->connect (new_stream, addr, timeout, local_sap, + reuse_addr, flags, perms) == -1 + && timeout != 0 && !(errno == EWOULDBLOCK || errno == ETIMEDOUT)) + ACE_ERROR ((LM_ERROR, "address %s, %p\n", + addr.get_path_name (), "ACE_UPIPE_Connector")); +} + + + + + diff --git a/ace/UPIPE_Stream.cpp b/ace/UPIPE_Stream.cpp new file mode 100644 index 00000000000..3c9bed43494 --- /dev/null +++ b/ace/UPIPE_Stream.cpp @@ -0,0 +1,206 @@ +// UPIPE_Stream.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/UPIPE_Stream.h" + +#if defined (ACE_HAS_THREADS) + +#if !defined (__ACE_INLINE__) +#include "ace/UPIPE_Stream.i" +#endif /* __ACE_INLINE__ */ + + +ACE_ALLOC_HOOK_DEFINE(ACE_UPIPE_Stream) + +int +ACE_UPIPE_Stream::control (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd, + void * val) +{ + ACE_TRACE ("ACE_UPIPE_Stream::control"); + return this->stream_.control (cmd, val); +} + +void +ACE_UPIPE_Stream::dump (void) const +{ + ACE_TRACE ("ACE_UPIPE_Stream::dump"); +} + +int +ACE_UPIPE_Stream::close (void) +{ + ACE_TRACE ("ACE_UPIPE_Stream::close"); + // Since the UPIPE should have been closed earlier we won't bother + // checking to see if closing it now fails. + + if (this->ACE_SPIPE::get_handle () != ACE_INVALID_HANDLE) + this->ACE_SPIPE::close (); + + // Close down the ACE_stream. + return this->stream_.close (0); +} + +int +ACE_UPIPE_Stream::get_remote_addr (ACE_UPIPE_Addr &remote_sap) const +{ + ACE_TRACE ("ACE_UPIPE_Stream::get_remote_addr"); + remote_sap = this->remote_addr_; + return 0; +} + +int +ACE_UPIPE_Stream::send (ACE_Message_Block *mb_p, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_UPIPE_Stream::send_msg"); + return this->stream_.put (mb_p, timeout) == -1 ? -1 : 0; +} + +int ACE_UPIPE_Stream::recv (ACE_Message_Block *& mb_p, + ACE_Time_Value *timeout) +{ + return this->stream_.get (mb_p, timeout) == -1 ? -1 : 0; +} + +// Send a buffer. + +int +ACE_UPIPE_Stream::send (const char *buffer, + size_t n, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_UPIPE_Stream::send"); + + ACE_Message_Block *mb_p; + + ACE_NEW_RETURN (mb_p, ACE_Message_Block (n), -1); + + mb_p->copy (buffer, n); + return this->stream_.put (mb_p, timeout) == -1 ? -1 : n; +} + +// Receive a buffer. + +int +ACE_UPIPE_Stream::recv (char *buffer, + size_t n, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_UPIPE_Stream::recv"); + // Index in buffer. + size_t bytes_read = 0; + + while (bytes_read < n) + if (this->mb_last_ != 0) + { + // We have remaining data in our last read Message_Buffer. + + if (this->remaining_ < n) + { + // The remaining data is not enough. + + ACE_OS::memcpy ((void *) &buffer[bytes_read], + this->mb_last_->rd_ptr (), + this->remaining_); + bytes_read += this->remaining_; + this->remaining_ = 0; + delete this->mb_last_; + this->mb_last_ = 0; + return bytes_read; + } + else + { + // The remaining data is at least enough. If there's + // more, we'll get it the next time through. + + ACE_OS::memcpy (&buffer[bytes_read], + this->mb_last_->rd_ptr (), + n); + bytes_read += n; + + // Advance rd_ptr. + this->mb_last_->rd_ptr (n); + this->remaining_ -= n; + + if (this->remaining_ == 0) + { + // Now the Message_Buffer is empty. + + delete this->mb_last_; + this->mb_last_ = 0; + } + } + } + else + { + // We have to get a new Message_Buffer from our stream. + + int result = this->stream_.get (this->mb_last_, timeout); + + if (result == -1) + { + if (errno == EWOULDBLOCK && bytes_read > 0) + // Return the number of bytes read before we timed out. + return bytes_read; + else + return -1; + } + this->remaining_ = this->mb_last_->size (); + } + + return bytes_read; +} + +int +ACE_UPIPE_Stream::send_n (const char *buf, + size_t n, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_UPIPE_Stream::send_n"); + + size_t bytes_written; + ssize_t len; + + for (bytes_written = 0; + bytes_written < n; + bytes_written += len) + { + len = this->send (buf + bytes_written, + n - bytes_written, + timeout); + + if (len == -1) + return -1; + } + + return bytes_written; +} + +int +ACE_UPIPE_Stream::recv_n (char *buf, + size_t n, + ACE_Time_Value *timeout) +{ + ACE_TRACE ("ACE_UPIPE_Stream::recv_n"); + size_t bytes_read; + ssize_t len; + + for (bytes_read = 0; + bytes_read < n; + bytes_read += len) + { + len = this->recv (buf + bytes_read, + n - bytes_read, + timeout); + if (len == -1) + return -1; + else if (len == 0) + break; + } + + return bytes_read; +} + +#endif /* ACE_HAS_THREADS */ + diff --git a/ace/UPIPE_Stream.h b/ace/UPIPE_Stream.h new file mode 100644 index 00000000000..23f084851c7 --- /dev/null +++ b/ace/UPIPE_Stream.h @@ -0,0 +1,117 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// UPIPE_Stream.h +// +// = AUTHOR +// Gerhard Lenzer and Douglas C. Schmidt +// +// ============================================================================ + +#if !defined ACE_UPIPE_STREAM_H +#define ACE_UPIPE_STREAM_H + +#include "ace/Stream.h" +#include "ace/Synch.h" +#include "ace/SPIPE.h" +#include "ace/Message_Queue.h" +#include "ace/UPIPE_Addr.h" + +#if defined (ACE_HAS_THREADS) + +// Use a typedef to make life easier later on. +typedef ACE_Stream<ACE_MT_SYNCH> MT_Stream; + +class ACE_Export ACE_UPIPE_Stream : public ACE_SPIPE + // = TITLE + // Defines the method that transfer data on a UPIPE. +{ + friend class ACE_UPIPE_Acceptor; + friend class ACE_UPIPE_Connector; +public: + // = Termination. + + int close (void); + // Shut down the UPIPE and release resources. + + ACE_HANDLE get_handle (void) const; + // Return the underlying I/O handle. + + // = Send/recv ACE Message_Blocks. + int send (ACE_Message_Block *mb_p, + ACE_Time_Value *timeout = 0); + // Send a message through the message queue. Returns -1 on error, + // else 0. + + int recv (ACE_Message_Block *&mb_p, + ACE_Time_Value *timeout = 0); + // Recv a message from the message queue. Returns -1 on error, else + // 0. + + // = Send/recv char buffers. + int send (const char *buffer, + size_t n, + ACE_Time_Value *timeout = 0); + // Send a buffer of <n> bytes through the message queue. Returns -1 + // on error, else number of bytes sent. + + int recv (char *buffer, + size_t n, + ACE_Time_Value *timeout = 0); + // Recv a buffer of upto <n> bytes from the message queue. Returns + // -1 on error, else number of bytes read. + + int send_n (const char *buffer, + size_t n, + ACE_Time_Value *timeout = 0); + // Send a buffer of exactly <n> bytes to the message queue. Returns + // -1 on error, else number of bytes written (which should == n). + + int recv_n (char *buffer, + size_t n, + ACE_Time_Value *timeout = 0); + // Recv a buffer of exactly <n> bytes from the message queue. + // Returns -1 on error, else the number of bytes read. + + int control (ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd, + void *val); + // Perform control operations on the UPIPE_Stream. + + int get_remote_addr (ACE_UPIPE_Addr &remote_sap) const; + // Return the remote address we are connected to. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Message_Block *mb_last_; + // To hold the last ACE_Message_Block read out of the stream. Thus + // allowing subsequent reads from one ACE_Message_Block + + size_t remaining_; + // Holds the number of bytes that are still available in mb_last_. + + ACE_UPIPE_Addr remote_addr_; + // Address of who we are connected to. + + MT_Stream stream_; + // Stream component used by the <UPIPE_Acceptor> and + // <UPIPE_Connector> to link together two UPIPE_Streams. +}; + +#if defined (__ACE_INLINE__) +#include "ace/UPIPE_Stream.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_THREADS */ +#endif /*ACE_UPIPE_STREAM_H */ diff --git a/ace/UPIPE_Stream.i b/ace/UPIPE_Stream.i new file mode 100644 index 00000000000..c2297fcffce --- /dev/null +++ b/ace/UPIPE_Stream.i @@ -0,0 +1,12 @@ +/* -*- C++ -*- */ +// $Id$ + +// UPIPE_Stream.i + +ACE_INLINE ACE_HANDLE +ACE_UPIPE_Stream::get_handle (void) const +{ + ACE_TRACE ("ACE_UPIPE_Stream::get_handle"); + return this->ACE_SPIPE::get_handle (); +} + diff --git a/ace/XtReactor.cpp b/ace/XtReactor.cpp new file mode 100644 index 00000000000..ac497c64e40 --- /dev/null +++ b/ace/XtReactor.cpp @@ -0,0 +1,327 @@ +// XtReactor.cpp +// $Id$ + +#define ACE_BUILD_DLL +#include "ace/Log_Msg.h" +#include "ace/Synch_T.h" +#include "ace/SOCK_Acceptor.h" +#include "ace/SOCK_Connector.h" +#include "ace/XtReactor.h" + +#if defined (ACE_HAS_XT) + +struct ACE_XtReactorID +{ + XtInputId id; + int good_id; +}; + +ACE_ALLOC_HOOK_DEFINE (ACE_XtReactor) + +// Must be called with lock held +ACE_XtReactor::ACE_XtReactor (XtAppContext context, + size_t size, + int restart, + ACE_Sig_Handler *h) + : ACE_Reactor (size, restart, h), + context_ (context), + id_len_ (0), + ids_ (0) +{ +} + +ACE_XtReactor::~ACE_XtReactor (void) +{ + delete this->ids_; +} + +// This is just the wait_for_multiple_events from ace/Reactor.cpp but +// we use the Xt functions to wait for an event, not select () +// +// FIXME - someday re-write this to use poll as well. + +int +ACE_XtReactor::wait_for_multiple_events (ACE_Handle_Set &rmask, + ACE_Handle_Set &wmask, + ACE_Handle_Set &emask, + ACE_Time_Value *max_wait_time) +{ + ACE_TRACE ("ACE_Reactor::wait_for_multiple_events"); +#if defined (ACE_USE_POLL) + u_long width = 0; +#endif /* ACE_USE_POLL */ + int nfound; + + do + { + max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time); + +#if defined (ACE_USE_POLL) + pollfd *phandles = this->handle_sets_to_poll_fds (width); + nfound = ACE_OS::poll (phandles, width, max_wait_time); +#else /* USE SELECT */ + size_t width = this->handler_rep_.max_handlep1 (); + rmask = this->rd_handle_mask_; + wmask = this->wr_handle_mask_; + emask = this->ex_handle_mask_; +#if 0 + nfound = ACE_OS::select (int (width), rmask, wmask, emask, max_wait_time); +#else + nfound = XtWaitForMultipleEvents (width, rmask, wmask, emask, max_wait_time); +#endif +#endif /* ACE_USE_POLL */ + } while (nfound == -1 && this->handle_error () > 0); + +#if defined (ACE_USE_POLL) + this->poll_fds_to_handle_sets (width, rmask, wmask, emask, nfound); +#endif /* ACE_USE_POLL */ + + if (nfound > 0) + { +#if !defined (ACE_WIN32) + rmask.sync (this->handler_rep_.max_handlep1 ()); + wmask.sync (this->handler_rep_.max_handlep1 ()); + emask.sync (this->handler_rep_.max_handlep1 ()); +#endif /* ACE_REACTOR_ALTERANTIVE_IMPL */ + } + return nfound; // Timed out or input available +} + +void +ACE_XtReactor::TimerCallbackProc (XtPointer closure, XtIntervalId *id) +{ + ACE_XtReactor *self = (ACE_XtReactor*)closure; + self->timeout_ = 0; + + ACE_DEBUG ((LM_DEBUG, "ACE_XtReactor::Timer on id %d\n", (int) *id)); + + ACE_Time_Value zero = ACE_Time_Value::zero; // my copy isn't const + + // Deal with any timer events + ACE_Handle_Set r, w, e; + self->dispatch (0, r, w, e); + self->reset_timeout (); +} + +// This could be made shorter if we know which *kind* of event we +// were about to get. Here we use select () to find out which one +// might be available. + +void ACE_XtReactor::InputCallbackProc (XtPointer closure, + int * source, + XtInputId *id) +{ + ACE_XtReactor * self = (ACE_XtReactor*)closure; + + ACE_DEBUG ((LM_DEBUG, "ACE_XtReactor::Input on fd %d\n", *source)); + + ACE_Time_Value zero = ACE_Time_Value::zero; // my copy isn't const + + ACE_Handle_Set r, w, e; + ACE_Handle_Set r2, w2, e2; + + // Deal with one file event + + // - read which kind of event + if (self->rd_handle_mask_.is_set (*source)) + r.set_bit (*source); + if (self->wr_handle_mask_.is_set (*source)) + w.set_bit (*source); + if (self->ex_handle_mask_.is_set (*source)) + e.set_bit (*source); + + int result = ACE_OS::select (*source+1, r, w, e, &zero); + + // - Use only that one file event (removes events for other files) + if (result > 0) + { + if (r.is_set (*source)) + r2.set_bit (*source); + if (w.is_set (*source)) + w2.set_bit (*source); + if (e.is_set (*source)) + e2.set_bit (*source); + + self->dispatch (1, r2, w2, e2); + } +} + +int ACE_XtReactor::XtWaitForMultipleEvents (int width, + ACE_Handle_Set &rmask, + ACE_Handle_Set &wmask, + ACE_Handle_Set &emask, + ACE_Time_Value *max_wait_time) +{ + // Check to make sure our fd's are all usable + + ACE_Handle_Set r (rmask), w (wmask), e (emask); + ACE_Time_Value zero = ACE_Time_Value::zero; // my copy isn't const + int result = ACE_OS::select (width, r, w, e, &zero); + + if (result < 0) // Bad file arguments... + return result; + + // Instead of waiting using select, just use the Xt mechanism to wait + // for a single event. + + // Wait for something to happen. + XtAppProcessEvent (context_, XtIMAll); + + // Now actually read the result needed by the Reactor using select. + result = ACE_OS::select (int (width), rmask, wmask, emask, &zero); + return result; +} + +XtAppContext ACE_XtReactor::context (void) +{ + return this->context_; +} + +int +ACE_XtReactor::attach (ACE_HANDLE handle, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_XtReactor::attach"); + + ACE_DEBUG ((LM_DEBUG, "+++%d\n", handle)); + + int result = ACE_Reactor::attach (handle, handler, mask); + + if (result < 0) + return -1; + + // Ensure the list of InputId's is big enough + if (ids_ == 0 || id_len_ < handle + 1) + { + ACE_XtReactorID *more; + ACE_NEW_RETURN (more, ACE_XtReactorID[handle + 1], -1); + int i; + for (i = 0; i < this->id_len_; i++) + more[i] = ids_[i]; + for (i = this->id_len_; i < handle + 1; i++) + more[i].good_id = 0; + id_len_ = handle + 1; + delete this->ids_; + ids_ = more; + } + + int condition = 0; + if (mask & ACE_Event_Handler::READ_MASK) + condition |= XtInputReadMask; + if (mask & ACE_Event_Handler::WRITE_MASK) + condition |= XtInputWriteMask; + if (mask & ACE_Event_Handler::EXCEPT_MASK) + condition |= XtInputExceptMask; + if (condition != 0) + { + if (ids_[handle].good_id) + XtRemoveInput (ids_[handle].id); + + ids_[handle].id = XtAppAddInput (context_, + handle, + (XtPointer)condition, + InputCallbackProc, + (XtPointer)this); + ids_[handle].good_id = 1; + } + return 0; +} + + +int +ACE_XtReactor::detach (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + ACE_TRACE ("ACE_XtReactor::detach"); + ACE_DEBUG ((LM_DEBUG, "---%d\n", handle)); + + int result = ACE_Reactor::detach (handle, mask); + + if (handle <= id_len_) + { + if (ids_[handle].good_id) + XtRemoveInput (ids_[handle].id); + else + ACE_DEBUG ((LM_DEBUG, "Handle id is not good %d\n", handle)); + ids_[handle].good_id = 0; + } + else + ACE_DEBUG ((LM_DEBUG, "Handle out of range %d\n", handle)); + + if (result < 0) + return result; + else + return 0; +} + +// The following functions ensure that there is an Xt timeout for the +// first timeout in the Reactor's Timer_Queue. + +void ACE_XtReactor::reset_timeout (void) +{ + if (timeout_) + XtRemoveTimeOut (timeout_); + timeout_ = 0; + + ACE_Time_Value *max_wait_time; + max_wait_time = this->timer_queue_->calculate_timeout (0); + + if (max_wait_time) + { + ACE_DEBUG ((LM_DEBUG, " %ld\n", max_wait_time->msec ())); + + timeout_ = + XtAppAddTimeOut (context_, max_wait_time->msec (), + TimerCallbackProc, (XtPointer) this); + } +} + +int +ACE_XtReactor::schedule_timer (ACE_Event_Handler *handler, + const void *arg, + const ACE_Time_Value &delta_time, + const ACE_Time_Value &interval) +{ + ACE_TRACE ("ACE_XtReactor::schedule_timer"); + ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1); + + int result = + ACE_Reactor::schedule_timer (handler, arg, delta_time, interval); + + if (result < 0) + return result; + + this->reset_timeout (); + return 0; +} + +int +ACE_XtReactor::cancel_timer (ACE_Event_Handler *handler) +{ + ACE_TRACE ("ACE_XtReactor::cancel_timer"); + + int result = ACE_Reactor::cancel_timer (handler); + + if (result < 0) + return -1; + + this->reset_timeout (); + return 0; +} + +int +ACE_XtReactor::cancel_timer (int timer_id, const void **arg) +{ + ACE_TRACE ("ACE_XtReactor::cancel_timer"); + + int result = ACE_Reactor::cancel_timer (timer_id, arg); + + if (result < 0) + return -1; + + this->reset_timeout (); + return 0; +} + +#endif /* ACE_HAS_XT */ diff --git a/ace/XtReactor.h b/ace/XtReactor.h new file mode 100644 index 00000000000..c26bf0677d6 --- /dev/null +++ b/ace/XtReactor.h @@ -0,0 +1,96 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// XtReactor.h +// +// = AUTHOR +// Eric C. Newton's <ecn@clark.net> and Douglas C. Schmidt <schmidt@cs.wustl.edu> +// +// ============================================================================ + +#if !defined (ACE_XTREACTOR_H) +#define ACE_XTREACTOR_H + +#include "ace/Reactor.h" + +#if defined (ACE_HAS_XT) + +#define String XtString +#include <X11/Intrinsic.h> +#undef String + +// Forward decl. +struct ACE_XtReactorID; + +class ACE_XtReactor : public ACE_Reactor + // = TITLE + // An object oriented event demultiplexor and event handler + // dispatcher that uses the X Toolkit functions. + // + // = DESCRIPTION + // The ACE_Reactor is an object-oriented event demultiplexor + // and event handler dispatcher. The sources of events that the + // ACE_Reactor waits for and dispatches includes I/O events, + // signals, and timer events. +{ +public: + // = Initialization and termination methods. + ACE_XtReactor (XtAppContext context, + size_t size = DEFAULT_SIZE, + int restart = 0, + ACE_Sig_Handler * = 0); + virtual ~ACE_XtReactor (void); + + XtAppContext context (void); + + // Register timers/handles with Xt. + virtual int attach (ACE_HANDLE handle, + ACE_Event_Handler *handler, + ACE_Reactor_Mask mask); + + virtual int detach (ACE_HANDLE handle, ACE_Reactor_Mask mask); + + virtual int schedule_timer (ACE_Event_Handler *handler, + const void *arg, + const ACE_Time_Value &delta_time, + const ACE_Time_Value &interval); + + virtual int cancel_timer (ACE_Event_Handler *handler); + virtual int cancel_timer (int timer_id, const void **arg); + +protected: + + virtual int wait_for_multiple_events (ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Time_Value *); + + virtual int XtWaitForMultipleEvents (int, + ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Handle_Set &, + ACE_Time_Value *); + + ACE_XtReactor (const ACE_Reactor &); + ACE_XtReactor &operator = (const ACE_Reactor &); + + XtAppContext context_; + struct ACE_XtReactorID *ids_; + int id_len_; + XtIntervalId timeout_; + +private: + void reset_timeout (void); + static void TimerCallbackProc (XtPointer closure, XtIntervalId *id); + static void InputCallbackProc (XtPointer closure, int* source, XtInputId *id); +}; +#endif /* ACE_HAS_XT */ + +#endif /* ACE_XTREACTOR_H */ diff --git a/ace/ace.mak b/ace/ace.mak new file mode 100644 index 00000000000..d67501e1148 --- /dev/null +++ b/ace/ace.mak @@ -0,0 +1,2197 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=ace - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to ace - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "ace - Win32 Release" && "$(CFG)" != "ace - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ace.mak" CFG="ace - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ace - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ace - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "ace - Win32 Debug"
+RSC=rc.exe
+MTL=mktyplib.exe
+CPP=cl.exe
+
+!IF "$(CFG)" == "ace - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\ace.dll"
+
+CLEAN :
+ -@erase ".\ace.dll"
+ -@erase ".\Release\DEV_IO.obj"
+ -@erase ".\Release\SOCK_Acceptor.obj"
+ -@erase ".\Release\Profile_Timer.obj"
+ -@erase ".\Release\Read_Buffer.obj"
+ -@erase ".\Release\Time_Request_Reply.obj"
+ -@erase ".\Release\LSOCK_Acceptor.obj"
+ -@erase ".\Release\Time_Value.obj"
+ -@erase ".\Release\LSOCK_Dgram.obj"
+ -@erase ".\Release\Process.obj"
+ -@erase ".\Release\ReactorEx.obj"
+ -@erase ".\Release\Handle_Set.obj"
+ -@erase ".\Release\FILE_IO.obj"
+ -@erase ".\Release\Token_Collection.obj"
+ -@erase ".\Release\LSOCK_CODgram.obj"
+ -@erase ".\Release\SOCK.obj"
+ -@erase ".\Release\LSOCK.obj"
+ -@erase ".\Release\SOCK_Dgram_Bcast.obj"
+ -@erase ".\Release\SPIPE_Connector.obj"
+ -@erase ".\Release\FILE_Addr.obj"
+ -@erase ".\Release\SV_Message.obj"
+ -@erase ".\Release\TLI.obj"
+ -@erase ".\Release\Addr.obj"
+ -@erase ".\Release\Process_Manager.obj"
+ -@erase ".\Release\Service_Main.obj"
+ -@erase ".\Release\SPIPE.obj"
+ -@erase ".\Release\TLI_Connector.obj"
+ -@erase ".\Release\Get_Opt.obj"
+ -@erase ".\Release\IO_Cntl_Msg.obj"
+ -@erase ".\Release\Pipe.obj"
+ -@erase ".\Release\UPIPE_Acceptor.obj"
+ -@erase ".\Release\Signal.obj"
+ -@erase ".\Release\FIFO.obj"
+ -@erase ".\Release\LSOCK_Stream.obj"
+ -@erase ".\Release\FIFO_Send.obj"
+ -@erase ".\Release\SString.obj"
+ -@erase ".\Release\Naming_Context.obj"
+ -@erase ".\Release\Memory_Pool.obj"
+ -@erase ".\Release\Log_Msg.obj"
+ -@erase ".\Release\Mem_Map.obj"
+ -@erase ".\Release\SV_Semaphore_Complex.obj"
+ -@erase ".\Release\FIFO_Recv_Msg.obj"
+ -@erase ".\Release\Synch.obj"
+ -@erase ".\Release\Thread_Manager.obj"
+ -@erase ".\Release\SV_Message_Queue.obj"
+ -@erase ".\Release\TLI_Acceptor.obj"
+ -@erase ".\Release\Shared_Object.obj"
+ -@erase ".\Release\SOCK_Dgram.obj"
+ -@erase ".\Release\ACE.obj"
+ -@erase ".\Release\Service_Object.obj"
+ -@erase ".\Release\Token.obj"
+ -@erase ".\Release\SOCK_CODgram.obj"
+ -@erase ".\Release\Name_Proxy.obj"
+ -@erase ".\Release\Service_Repository.obj"
+ -@erase ".\Release\Event_Handler.obj"
+ -@erase ".\Release\Date_Time.obj"
+ -@erase ".\Release\SPIPE_Addr.obj"
+ -@erase ".\Release\Malloc.obj"
+ -@erase ".\Release\SOCK_Dgram_Mcast.obj"
+ -@erase ".\Release\Token_Invariants.obj"
+ -@erase ".\Release\DEV_Connector.obj"
+ -@erase ".\Release\FILE_Connector.obj"
+ -@erase ".\Release\Log_Record.obj"
+ -@erase ".\Release\Multiplexor.obj"
+ -@erase ".\Release\Shared_Memory_MM.obj"
+ -@erase ".\Release\Message_Block.obj"
+ -@erase ".\Release\Proactor.obj"
+ -@erase ".\Release\Remote_Tokens.obj"
+ -@erase ".\Release\Service_Record.obj"
+ -@erase ".\Release\Timer_Queue.obj"
+ -@erase ".\Release\SV_Shared_Memory.obj"
+ -@erase ".\Release\Remote_Name_Space.obj"
+ -@erase ".\Release\UPIPE_Connector.obj"
+ -@erase ".\Release\SPIPE_Stream.obj"
+ -@erase ".\Release\TLI_Stream.obj"
+ -@erase ".\Release\OS.obj"
+ -@erase ".\Release\Service_Config.obj"
+ -@erase ".\Release\IPC_SAP.obj"
+ -@erase ".\Release\Trace.obj"
+ -@erase ".\Release\Obstack.obj"
+ -@erase ".\Release\High_Res_Timer.obj"
+ -@erase ".\Release\Name_Request_Reply.obj"
+ -@erase ".\Release\SOCK_Connector.obj"
+ -@erase ".\Release\Local_Name_Space.obj"
+ -@erase ".\Release\FILE.obj"
+ -@erase ".\Release\DEV_Addr.obj"
+ -@erase ".\Release\UPIPE_Stream.obj"
+ -@erase ".\Release\SOCK_IO.obj"
+ -@erase ".\Release\SPIPE_Acceptor.obj"
+ -@erase ".\Release\FIFO_Send_Msg.obj"
+ -@erase ".\Release\System_Time.obj"
+ -@erase ".\Release\INET_Addr.obj"
+ -@erase ".\Release\FIFO_Recv.obj"
+ -@erase ".\Release\CORBA_Handler.obj"
+ -@erase ".\Release\Reactor.obj"
+ -@erase ".\Release\DEV.obj"
+ -@erase ".\Release\ARGV.obj"
+ -@erase ".\Release\Token_Request_Reply.obj"
+ -@erase ".\Release\Token_Manager.obj"
+ -@erase ".\Release\Name_Space.obj"
+ -@erase ".\Release\Thread.obj"
+ -@erase ".\Release\Dump.obj"
+ -@erase ".\Release\Svc_Conf_l.obj"
+ -@erase ".\Release\Shared_Memory_SV.obj"
+ -@erase ".\Release\Synch_Options.obj"
+ -@erase ".\Release\SOCK_Stream.obj"
+ -@erase ".\Release\Service_Manager.obj"
+ -@erase ".\Release\IO_SAP.obj"
+ -@erase ".\Release\Dynamic.obj"
+ -@erase ".\Release\SV_Semaphore_Simple.obj"
+ -@erase ".\Release\Local_Tokens.obj"
+ -@erase ".\Release\Svc_Conf_y.obj"
+ -@erase ".\Release\Parse_Node.obj"
+ -@erase ".\Release\UNIX_Addr.obj"
+ -@erase ".\Release\LSOCK_Connector.obj"
+ -@erase ".\Release\TTY_IO.obj"
+ -@erase ".\ace.lib"
+ -@erase ".\ace.exp"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/ace.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/ace.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/ace.pdb" /machine:I386 /out:"$(OUTDIR)/ace.dll"\
+ /implib:"$(OUTDIR)/ace.lib"
+LINK32_OBJS= \
+ "$(INTDIR)/DEV_IO.obj" \
+ "$(INTDIR)/SOCK_Acceptor.obj" \
+ "$(INTDIR)/Profile_Timer.obj" \
+ "$(INTDIR)/Read_Buffer.obj" \
+ "$(INTDIR)/Time_Request_Reply.obj" \
+ "$(INTDIR)/LSOCK_Acceptor.obj" \
+ "$(INTDIR)/Time_Value.obj" \
+ "$(INTDIR)/LSOCK_Dgram.obj" \
+ "$(INTDIR)/Process.obj" \
+ "$(INTDIR)/ReactorEx.obj" \
+ "$(INTDIR)/Handle_Set.obj" \
+ "$(INTDIR)/FILE_IO.obj" \
+ "$(INTDIR)/Token_Collection.obj" \
+ "$(INTDIR)/LSOCK_CODgram.obj" \
+ "$(INTDIR)/SOCK.obj" \
+ "$(INTDIR)/LSOCK.obj" \
+ "$(INTDIR)/SOCK_Dgram_Bcast.obj" \
+ "$(INTDIR)/SPIPE_Connector.obj" \
+ "$(INTDIR)/FILE_Addr.obj" \
+ "$(INTDIR)/SV_Message.obj" \
+ "$(INTDIR)/TLI.obj" \
+ "$(INTDIR)/Addr.obj" \
+ "$(INTDIR)/Process_Manager.obj" \
+ "$(INTDIR)/Service_Main.obj" \
+ "$(INTDIR)/SPIPE.obj" \
+ "$(INTDIR)/TLI_Connector.obj" \
+ "$(INTDIR)/Get_Opt.obj" \
+ "$(INTDIR)/IO_Cntl_Msg.obj" \
+ "$(INTDIR)/Pipe.obj" \
+ "$(INTDIR)/UPIPE_Acceptor.obj" \
+ "$(INTDIR)/Signal.obj" \
+ "$(INTDIR)/FIFO.obj" \
+ "$(INTDIR)/LSOCK_Stream.obj" \
+ "$(INTDIR)/FIFO_Send.obj" \
+ "$(INTDIR)/SString.obj" \
+ "$(INTDIR)/Naming_Context.obj" \
+ "$(INTDIR)/Memory_Pool.obj" \
+ "$(INTDIR)/Log_Msg.obj" \
+ "$(INTDIR)/Mem_Map.obj" \
+ "$(INTDIR)/SV_Semaphore_Complex.obj" \
+ "$(INTDIR)/FIFO_Recv_Msg.obj" \
+ "$(INTDIR)/Synch.obj" \
+ "$(INTDIR)/Thread_Manager.obj" \
+ "$(INTDIR)/SV_Message_Queue.obj" \
+ "$(INTDIR)/TLI_Acceptor.obj" \
+ "$(INTDIR)/Shared_Object.obj" \
+ "$(INTDIR)/SOCK_Dgram.obj" \
+ "$(INTDIR)/ACE.obj" \
+ "$(INTDIR)/Service_Object.obj" \
+ "$(INTDIR)/Token.obj" \
+ "$(INTDIR)/SOCK_CODgram.obj" \
+ "$(INTDIR)/Name_Proxy.obj" \
+ "$(INTDIR)/Service_Repository.obj" \
+ "$(INTDIR)/Event_Handler.obj" \
+ "$(INTDIR)/Date_Time.obj" \
+ "$(INTDIR)/SPIPE_Addr.obj" \
+ "$(INTDIR)/Malloc.obj" \
+ "$(INTDIR)/SOCK_Dgram_Mcast.obj" \
+ "$(INTDIR)/Token_Invariants.obj" \
+ "$(INTDIR)/DEV_Connector.obj" \
+ "$(INTDIR)/FILE_Connector.obj" \
+ "$(INTDIR)/Log_Record.obj" \
+ "$(INTDIR)/Multiplexor.obj" \
+ "$(INTDIR)/Shared_Memory_MM.obj" \
+ "$(INTDIR)/Message_Block.obj" \
+ "$(INTDIR)/Proactor.obj" \
+ "$(INTDIR)/Remote_Tokens.obj" \
+ "$(INTDIR)/Service_Record.obj" \
+ "$(INTDIR)/Timer_Queue.obj" \
+ "$(INTDIR)/SV_Shared_Memory.obj" \
+ "$(INTDIR)/Remote_Name_Space.obj" \
+ "$(INTDIR)/UPIPE_Connector.obj" \
+ "$(INTDIR)/SPIPE_Stream.obj" \
+ "$(INTDIR)/TLI_Stream.obj" \
+ "$(INTDIR)/OS.obj" \
+ "$(INTDIR)/Service_Config.obj" \
+ "$(INTDIR)/IPC_SAP.obj" \
+ "$(INTDIR)/Trace.obj" \
+ "$(INTDIR)/Obstack.obj" \
+ "$(INTDIR)/High_Res_Timer.obj" \
+ "$(INTDIR)/Name_Request_Reply.obj" \
+ "$(INTDIR)/SOCK_Connector.obj" \
+ "$(INTDIR)/Local_Name_Space.obj" \
+ "$(INTDIR)/FILE.obj" \
+ "$(INTDIR)/DEV_Addr.obj" \
+ "$(INTDIR)/UPIPE_Stream.obj" \
+ "$(INTDIR)/SOCK_IO.obj" \
+ "$(INTDIR)/SPIPE_Acceptor.obj" \
+ "$(INTDIR)/FIFO_Send_Msg.obj" \
+ "$(INTDIR)/System_Time.obj" \
+ "$(INTDIR)/INET_Addr.obj" \
+ "$(INTDIR)/FIFO_Recv.obj" \
+ "$(INTDIR)/CORBA_Handler.obj" \
+ "$(INTDIR)/Reactor.obj" \
+ "$(INTDIR)/DEV.obj" \
+ "$(INTDIR)/ARGV.obj" \
+ "$(INTDIR)/Token_Request_Reply.obj" \
+ "$(INTDIR)/Token_Manager.obj" \
+ "$(INTDIR)/Name_Space.obj" \
+ "$(INTDIR)/Thread.obj" \
+ "$(INTDIR)/Dump.obj" \
+ "$(INTDIR)/Svc_Conf_l.obj" \
+ "$(INTDIR)/Shared_Memory_SV.obj" \
+ "$(INTDIR)/Synch_Options.obj" \
+ "$(INTDIR)/SOCK_Stream.obj" \
+ "$(INTDIR)/Service_Manager.obj" \
+ "$(INTDIR)/IO_SAP.obj" \
+ "$(INTDIR)/Dynamic.obj" \
+ "$(INTDIR)/SV_Semaphore_Simple.obj" \
+ "$(INTDIR)/Local_Tokens.obj" \
+ "$(INTDIR)/Svc_Conf_y.obj" \
+ "$(INTDIR)/Parse_Node.obj" \
+ "$(INTDIR)/UNIX_Addr.obj" \
+ "$(INTDIR)/LSOCK_Connector.obj" \
+ "$(INTDIR)/TTY_IO.obj"
+
+"$(OUTDIR)\ace.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "ace - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\ace.dll"
+
+CLEAN :
+ -@erase ".\Debug\vc40.pdb"
+ -@erase ".\Debug\vc40.idb"
+ -@erase ".\ace.dll"
+ -@erase ".\Debug\Date_Time.obj"
+ -@erase ".\Debug\Token_Collection.obj"
+ -@erase ".\Debug\LSOCK_Connector.obj"
+ -@erase ".\Debug\SOCK_Dgram_Bcast.obj"
+ -@erase ".\Debug\LSOCK_Dgram.obj"
+ -@erase ".\Debug\SPIPE_Acceptor.obj"
+ -@erase ".\Debug\Event_Handler.obj"
+ -@erase ".\Debug\Synch_Options.obj"
+ -@erase ".\Debug\Process.obj"
+ -@erase ".\Debug\FILE_IO.obj"
+ -@erase ".\Debug\Trace.obj"
+ -@erase ".\Debug\Signal.obj"
+ -@erase ".\Debug\TLI_Acceptor.obj"
+ -@erase ".\Debug\DEV_Addr.obj"
+ -@erase ".\Debug\SOCK_CODgram.obj"
+ -@erase ".\Debug\SPIPE_Connector.obj"
+ -@erase ".\Debug\ACE.obj"
+ -@erase ".\Debug\Remote_Name_Space.obj"
+ -@erase ".\Debug\IO_Cntl_Msg.obj"
+ -@erase ".\Debug\Process_Manager.obj"
+ -@erase ".\Debug\SOCK.obj"
+ -@erase ".\Debug\Timer_Queue.obj"
+ -@erase ".\Debug\Name_Space.obj"
+ -@erase ".\Debug\Get_Opt.obj"
+ -@erase ".\Debug\Svc_Conf_l.obj"
+ -@erase ".\Debug\Message_Block.obj"
+ -@erase ".\Debug\Service_Repository.obj"
+ -@erase ".\Debug\Addr.obj"
+ -@erase ".\Debug\Remote_Tokens.obj"
+ -@erase ".\Debug\Pipe.obj"
+ -@erase ".\Debug\SString.obj"
+ -@erase ".\Debug\IO_SAP.obj"
+ -@erase ".\Debug\FIFO.obj"
+ -@erase ".\Debug\Svc_Conf_y.obj"
+ -@erase ".\Debug\Log_Msg.obj"
+ -@erase ".\Debug\Mem_Map.obj"
+ -@erase ".\Debug\SV_Message_Queue.obj"
+ -@erase ".\Debug\Token_Request_Reply.obj"
+ -@erase ".\Debug\Parse_Node.obj"
+ -@erase ".\Debug\SV_Semaphore_Complex.obj"
+ -@erase ".\Debug\System_Time.obj"
+ -@erase ".\Debug\INET_Addr.obj"
+ -@erase ".\Debug\LSOCK_Acceptor.obj"
+ -@erase ".\Debug\FIFO_Recv.obj"
+ -@erase ".\Debug\Time_Value.obj"
+ -@erase ".\Debug\Malloc.obj"
+ -@erase ".\Debug\FILE_Connector.obj"
+ -@erase ".\Debug\LSOCK_Stream.obj"
+ -@erase ".\Debug\Handle_Set.obj"
+ -@erase ".\Debug\FIFO_Send_Msg.obj"
+ -@erase ".\Debug\CORBA_Handler.obj"
+ -@erase ".\Debug\SOCK_Dgram_Mcast.obj"
+ -@erase ".\Debug\SV_Message.obj"
+ -@erase ".\Debug\SOCK_Stream.obj"
+ -@erase ".\Debug\Token_Invariants.obj"
+ -@erase ".\Debug\Token_Manager.obj"
+ -@erase ".\Debug\SV_Semaphore_Simple.obj"
+ -@erase ".\Debug\Shared_Memory_MM.obj"
+ -@erase ".\Debug\OS.obj"
+ -@erase ".\Debug\UPIPE_Acceptor.obj"
+ -@erase ".\Debug\Service_Config.obj"
+ -@erase ".\Debug\LSOCK.obj"
+ -@erase ".\Debug\Multiplexor.obj"
+ -@erase ".\Debug\SV_Shared_Memory.obj"
+ -@erase ".\Debug\DEV.obj"
+ -@erase ".\Debug\SOCK_Connector.obj"
+ -@erase ".\Debug\SPIPE.obj"
+ -@erase ".\Debug\UNIX_Addr.obj"
+ -@erase ".\Debug\Naming_Context.obj"
+ -@erase ".\Debug\Read_Buffer.obj"
+ -@erase ".\Debug\Thread_Manager.obj"
+ -@erase ".\Debug\ReactorEx.obj"
+ -@erase ".\Debug\UPIPE_Connector.obj"
+ -@erase ".\Debug\Local_Name_Space.obj"
+ -@erase ".\Debug\SOCK_Acceptor.obj"
+ -@erase ".\Debug\Profile_Timer.obj"
+ -@erase ".\Debug\IPC_SAP.obj"
+ -@erase ".\Debug\FILE_Addr.obj"
+ -@erase ".\Debug\Service_Object.obj"
+ -@erase ".\Debug\Obstack.obj"
+ -@erase ".\Debug\DEV_Connector.obj"
+ -@erase ".\Debug\SOCK_Dgram.obj"
+ -@erase ".\Debug\LSOCK_CODgram.obj"
+ -@erase ".\Debug\Local_Tokens.obj"
+ -@erase ".\Debug\Name_Proxy.obj"
+ -@erase ".\Debug\Thread.obj"
+ -@erase ".\Debug\Synch.obj"
+ -@erase ".\Debug\SOCK_IO.obj"
+ -@erase ".\Debug\TLI_Connector.obj"
+ -@erase ".\Debug\SPIPE_Addr.obj"
+ -@erase ".\Debug\FILE.obj"
+ -@erase ".\Debug\FIFO_Send.obj"
+ -@erase ".\Debug\Shared_Memory_SV.obj"
+ -@erase ".\Debug\Time_Request_Reply.obj"
+ -@erase ".\Debug\SPIPE_Stream.obj"
+ -@erase ".\Debug\Token.obj"
+ -@erase ".\Debug\Reactor.obj"
+ -@erase ".\Debug\Memory_Pool.obj"
+ -@erase ".\Debug\Log_Record.obj"
+ -@erase ".\Debug\Service_Main.obj"
+ -@erase ".\Debug\TLI.obj"
+ -@erase ".\Debug\ARGV.obj"
+ -@erase ".\Debug\Service_Record.obj"
+ -@erase ".\Debug\UPIPE_Stream.obj"
+ -@erase ".\Debug\DEV_IO.obj"
+ -@erase ".\Debug\Name_Request_Reply.obj"
+ -@erase ".\Debug\Dump.obj"
+ -@erase ".\Debug\Service_Manager.obj"
+ -@erase ".\Debug\FIFO_Recv_Msg.obj"
+ -@erase ".\Debug\Proactor.obj"
+ -@erase ".\Debug\Dynamic.obj"
+ -@erase ".\Debug\TLI_Stream.obj"
+ -@erase ".\Debug\High_Res_Timer.obj"
+ -@erase ".\Debug\Shared_Object.obj"
+ -@erase ".\Debug\TTY_IO.obj"
+ -@erase ".\ace.ilk"
+ -@erase ".\ace.lib"
+ -@erase ".\ace.exp"
+ -@erase ".\ace.pdb"
+
+"$(INTDIR)" :
+ if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\
+ /Fp"$(INTDIR)/ace.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/ace.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib wsock32.lib advapi32.lib /nologo /subsystem:windows /dll\
+ /incremental:yes /pdb:"$(OUTDIR)/ace.pdb" /debug /machine:I386\
+ /out:"$(OUTDIR)/ace.dll" /implib:"$(OUTDIR)/ace.lib"
+LINK32_OBJS= \
+ "$(INTDIR)/Date_Time.obj" \
+ "$(INTDIR)/Token_Collection.obj" \
+ "$(INTDIR)/LSOCK_Connector.obj" \
+ "$(INTDIR)/SOCK_Dgram_Bcast.obj" \
+ "$(INTDIR)/LSOCK_Dgram.obj" \
+ "$(INTDIR)/SPIPE_Acceptor.obj" \
+ "$(INTDIR)/Event_Handler.obj" \
+ "$(INTDIR)/Synch_Options.obj" \
+ "$(INTDIR)/Process.obj" \
+ "$(INTDIR)/FILE_IO.obj" \
+ "$(INTDIR)/Trace.obj" \
+ "$(INTDIR)/Signal.obj" \
+ "$(INTDIR)/TLI_Acceptor.obj" \
+ "$(INTDIR)/DEV_Addr.obj" \
+ "$(INTDIR)/SOCK_CODgram.obj" \
+ "$(INTDIR)/SPIPE_Connector.obj" \
+ "$(INTDIR)/ACE.obj" \
+ "$(INTDIR)/Remote_Name_Space.obj" \
+ "$(INTDIR)/IO_Cntl_Msg.obj" \
+ "$(INTDIR)/Process_Manager.obj" \
+ "$(INTDIR)/SOCK.obj" \
+ "$(INTDIR)/Timer_Queue.obj" \
+ "$(INTDIR)/Name_Space.obj" \
+ "$(INTDIR)/Get_Opt.obj" \
+ "$(INTDIR)/Svc_Conf_l.obj" \
+ "$(INTDIR)/Message_Block.obj" \
+ "$(INTDIR)/Service_Repository.obj" \
+ "$(INTDIR)/Addr.obj" \
+ "$(INTDIR)/Remote_Tokens.obj" \
+ "$(INTDIR)/Pipe.obj" \
+ "$(INTDIR)/SString.obj" \
+ "$(INTDIR)/IO_SAP.obj" \
+ "$(INTDIR)/FIFO.obj" \
+ "$(INTDIR)/Svc_Conf_y.obj" \
+ "$(INTDIR)/Log_Msg.obj" \
+ "$(INTDIR)/Mem_Map.obj" \
+ "$(INTDIR)/SV_Message_Queue.obj" \
+ "$(INTDIR)/Token_Request_Reply.obj" \
+ "$(INTDIR)/Parse_Node.obj" \
+ "$(INTDIR)/SV_Semaphore_Complex.obj" \
+ "$(INTDIR)/System_Time.obj" \
+ "$(INTDIR)/INET_Addr.obj" \
+ "$(INTDIR)/LSOCK_Acceptor.obj" \
+ "$(INTDIR)/FIFO_Recv.obj" \
+ "$(INTDIR)/Time_Value.obj" \
+ "$(INTDIR)/Malloc.obj" \
+ "$(INTDIR)/FILE_Connector.obj" \
+ "$(INTDIR)/LSOCK_Stream.obj" \
+ "$(INTDIR)/Handle_Set.obj" \
+ "$(INTDIR)/FIFO_Send_Msg.obj" \
+ "$(INTDIR)/CORBA_Handler.obj" \
+ "$(INTDIR)/SOCK_Dgram_Mcast.obj" \
+ "$(INTDIR)/SV_Message.obj" \
+ "$(INTDIR)/SOCK_Stream.obj" \
+ "$(INTDIR)/Token_Invariants.obj" \
+ "$(INTDIR)/Token_Manager.obj" \
+ "$(INTDIR)/SV_Semaphore_Simple.obj" \
+ "$(INTDIR)/Shared_Memory_MM.obj" \
+ "$(INTDIR)/OS.obj" \
+ "$(INTDIR)/UPIPE_Acceptor.obj" \
+ "$(INTDIR)/Service_Config.obj" \
+ "$(INTDIR)/LSOCK.obj" \
+ "$(INTDIR)/Multiplexor.obj" \
+ "$(INTDIR)/SV_Shared_Memory.obj" \
+ "$(INTDIR)/DEV.obj" \
+ "$(INTDIR)/SOCK_Connector.obj" \
+ "$(INTDIR)/SPIPE.obj" \
+ "$(INTDIR)/UNIX_Addr.obj" \
+ "$(INTDIR)/Naming_Context.obj" \
+ "$(INTDIR)/Read_Buffer.obj" \
+ "$(INTDIR)/Thread_Manager.obj" \
+ "$(INTDIR)/ReactorEx.obj" \
+ "$(INTDIR)/UPIPE_Connector.obj" \
+ "$(INTDIR)/Local_Name_Space.obj" \
+ "$(INTDIR)/SOCK_Acceptor.obj" \
+ "$(INTDIR)/Profile_Timer.obj" \
+ "$(INTDIR)/IPC_SAP.obj" \
+ "$(INTDIR)/FILE_Addr.obj" \
+ "$(INTDIR)/Service_Object.obj" \
+ "$(INTDIR)/Obstack.obj" \
+ "$(INTDIR)/DEV_Connector.obj" \
+ "$(INTDIR)/SOCK_Dgram.obj" \
+ "$(INTDIR)/LSOCK_CODgram.obj" \
+ "$(INTDIR)/Local_Tokens.obj" \
+ "$(INTDIR)/Name_Proxy.obj" \
+ "$(INTDIR)/Thread.obj" \
+ "$(INTDIR)/Synch.obj" \
+ "$(INTDIR)/SOCK_IO.obj" \
+ "$(INTDIR)/TLI_Connector.obj" \
+ "$(INTDIR)/SPIPE_Addr.obj" \
+ "$(INTDIR)/FILE.obj" \
+ "$(INTDIR)/FIFO_Send.obj" \
+ "$(INTDIR)/Shared_Memory_SV.obj" \
+ "$(INTDIR)/Time_Request_Reply.obj" \
+ "$(INTDIR)/SPIPE_Stream.obj" \
+ "$(INTDIR)/Token.obj" \
+ "$(INTDIR)/Reactor.obj" \
+ "$(INTDIR)/Memory_Pool.obj" \
+ "$(INTDIR)/Log_Record.obj" \
+ "$(INTDIR)/Service_Main.obj" \
+ "$(INTDIR)/TLI.obj" \
+ "$(INTDIR)/ARGV.obj" \
+ "$(INTDIR)/Service_Record.obj" \
+ "$(INTDIR)/UPIPE_Stream.obj" \
+ "$(INTDIR)/DEV_IO.obj" \
+ "$(INTDIR)/Name_Request_Reply.obj" \
+ "$(INTDIR)/Dump.obj" \
+ "$(INTDIR)/Service_Manager.obj" \
+ "$(INTDIR)/FIFO_Recv_Msg.obj" \
+ "$(INTDIR)/Proactor.obj" \
+ "$(INTDIR)/Dynamic.obj" \
+ "$(INTDIR)/TLI_Stream.obj" \
+ "$(INTDIR)/High_Res_Timer.obj" \
+ "$(INTDIR)/Shared_Object.obj" \
+ "$(INTDIR)/TTY_IO.obj"
+
+"$(OUTDIR)\ace.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "ace - Win32 Release"
+# Name "ace - Win32 Debug"
+
+!IF "$(CFG)" == "ace - Win32 Release"
+
+!ELSEIF "$(CFG)" == "ace - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\UPIPE_Stream.cpp
+NODEP_CPP_UPIPE=\
+ ".\ace\UPIPE_Stream.h"\
+ ".\ace\UPIPE_Stream.i"\
+
+
+"$(INTDIR)\UPIPE_Stream.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\UPIPE_Connector.cpp
+NODEP_CPP_UPIPE_=\
+ ".\ace\UPIPE_Connector.h"\
+
+
+"$(INTDIR)\UPIPE_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\UPIPE_Acceptor.cpp
+NODEP_CPP_UPIPE_A=\
+ ".\ace\UPIPE_Acceptor.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\UPIPE_Acceptor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\UNIX_Addr.cpp
+NODEP_CPP_UNIX_=\
+ ".\ace\UNIX_Addr.h"\
+ ".\ace\UNIX_Addr.i"\
+
+
+"$(INTDIR)\UNIX_Addr.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Trace.cpp
+NODEP_CPP_TRACE=\
+ ".\ace\config.h"\
+ ".\ace\ACE.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Trace.h"\
+ ".\ace\Trace.i"\
+
+
+"$(INTDIR)\Trace.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Token_Request_Reply.cpp
+NODEP_CPP_TOKEN=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Token_Request_Reply.h"\
+ ".\ace\Token_Request_Reply.i"\
+
+
+"$(INTDIR)\Token_Request_Reply.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Token_Manager.cpp
+NODEP_CPP_TOKEN_=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Token_Manager.h"\
+ ".\ace\Token_Manager.i"\
+
+
+"$(INTDIR)\Token_Manager.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Token_Collection.cpp
+NODEP_CPP_TOKEN_C=\
+ ".\ace\Token_Collection.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Token_Collection.i"\
+
+
+"$(INTDIR)\Token_Collection.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Token.cpp
+NODEP_CPP_TOKEN_CP=\
+ ".\ace\Thread.h"\
+ ".\ace\Time_Value.h"\
+ ".\ace\Token.h"\
+ ".\ace\Token.i"\
+
+
+"$(INTDIR)\Token.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\TLI_Stream.cpp
+NODEP_CPP_TLI_S=\
+ ".\ace\TLI_Stream.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\TLI_Stream.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\TLI_Connector.cpp
+NODEP_CPP_TLI_C=\
+ ".\ace\Handle_Set.h"\
+ ".\ace\TLI_Connector.h"\
+ ".\ace\Time_Value.h"\
+
+
+"$(INTDIR)\TLI_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\TLI_Acceptor.cpp
+NODEP_CPP_TLI_A=\
+ ".\ace\TLI_Acceptor.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\TLI_Acceptor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\TLI.cpp
+NODEP_CPP_TLI_CP=\
+ ".\ace\TLI.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\TLI.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Timer_Queue.cpp
+NODEP_CPP_TIMER=\
+ ".\ace\Timer_Queue.h"\
+
+
+"$(INTDIR)\Timer_Queue.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Time_Value.cpp
+NODEP_CPP_TIME_=\
+ ".\ace\ACE.h"\
+ ".\ace\Time_Value.h"\
+ ".\ace\Time_Value.i"\
+
+
+"$(INTDIR)\Time_Value.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Time_Request_Reply.cpp
+NODEP_CPP_TIME_R=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Time_Request_Reply.h"\
+
+
+"$(INTDIR)\Time_Request_Reply.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Thread_Manager.cpp
+NODEP_CPP_THREA=\
+ ".\ace\Thread_Manager.h"\
+ ".\ace\Thread_Manager.i"\
+
+
+"$(INTDIR)\Thread_Manager.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Thread.cpp
+NODEP_CPP_THREAD=\
+ ".\ace\Thread.h"\
+ ".\ace\Thread.i"\
+
+
+"$(INTDIR)\Thread.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\System_Time.cpp
+NODEP_CPP_SYSTE=\
+ ".\ace\Time_Value.h"\
+ ".\ace\System_Time.h"\
+
+
+"$(INTDIR)\System_Time.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Synch_Options.cpp
+NODEP_CPP_SYNCH=\
+ ".\ace\Synch_Options.h"\
+
+
+"$(INTDIR)\Synch_Options.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Synch.cpp
+NODEP_CPP_SYNCH_=\
+ ".\ace\Thread.h"\
+ ".\ace\Synch.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Time_Value.h"\
+ ".\ace\Synch.i"\
+
+
+"$(INTDIR)\Synch.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Svc_Conf_y.cpp
+NODEP_CPP_SVC_C=\
+ ".\ace\ARGV.h"\
+ ".\ace\Svc_Conf.h"\
+ ".\ace\Module.h"\
+ ".\ace\Stream.h"\
+
+
+"$(INTDIR)\Svc_Conf_y.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Svc_Conf_l.cpp
+NODEP_CPP_SVC_CO=\
+ ".\ace\Svc_Conf.h"\
+ ".\ace\Svc_Conf_Tokens.h"\
+
+
+"$(INTDIR)\Svc_Conf_l.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SV_Shared_Memory.cpp
+NODEP_CPP_SV_SH=\
+ ".\ace\SV_Shared_Memory.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\SV_Shared_Memory.i"\
+
+
+"$(INTDIR)\SV_Shared_Memory.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SV_Semaphore_Simple.cpp
+NODEP_CPP_SV_SE=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\SV_Semaphore_Simple.h"\
+
+
+"$(INTDIR)\SV_Semaphore_Simple.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SV_Semaphore_Complex.cpp
+NODEP_CPP_SV_SEM=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\SV_Semaphore_Complex.h"\
+
+
+"$(INTDIR)\SV_Semaphore_Complex.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SV_Message_Queue.cpp
+NODEP_CPP_SV_ME=\
+ ".\ace\SV_Message_Queue.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\SV_Message_Queue.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SV_Message.cpp
+NODEP_CPP_SV_MES=\
+ ".\ace\SV_Message.h"\
+ ".\ace\SV_Message.i"\
+
+
+"$(INTDIR)\SV_Message.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SString.cpp
+NODEP_CPP_SSTRI=\
+ ".\ace\Malloc.h"\
+ ".\ace\Service_Config.h"\
+ ".\ace\SString.h"\
+ ".\ace\SString.i"\
+
+
+"$(INTDIR)\SString.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SPIPE_Stream.cpp
+NODEP_CPP_SPIPE=\
+ ".\ace\SPIPE_Stream.h"\
+
+
+"$(INTDIR)\SPIPE_Stream.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SPIPE_Connector.cpp
+NODEP_CPP_SPIPE_=\
+ ".\ace\SPIPE_Connector.h"\
+
+
+"$(INTDIR)\SPIPE_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SPIPE_Addr.cpp
+NODEP_CPP_SPIPE_A=\
+ ".\ace\SPIPE_Addr.h"\
+ ".\ace\SPIPE_Addr.i"\
+
+
+"$(INTDIR)\SPIPE_Addr.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SPIPE_Acceptor.cpp
+NODEP_CPP_SPIPE_AC=\
+ ".\ace\SPIPE_Acceptor.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\SPIPE_Acceptor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SPIPE.cpp
+NODEP_CPP_SPIPE_C=\
+ ".\ace\SPIPE.h"\
+
+
+"$(INTDIR)\SPIPE.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_Stream.cpp
+NODEP_CPP_SOCK_=\
+ ".\ace\SOCK_Stream.h"\
+
+
+"$(INTDIR)\SOCK_Stream.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_IO.cpp
+NODEP_CPP_SOCK_I=\
+ ".\ace\SOCK_IO.h"\
+
+
+"$(INTDIR)\SOCK_IO.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_Dgram_Mcast.cpp
+NODEP_CPP_SOCK_D=\
+ ".\ace\SOCK_Dgram_Mcast.h"\
+ ".\ace\INET_Addr.h"\
+
+
+"$(INTDIR)\SOCK_Dgram_Mcast.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_Dgram_Bcast.cpp
+NODEP_CPP_SOCK_DG=\
+ ".\ace\SOCK_Dgram_Bcast.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\SOCK_Dgram_Bcast.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_Dgram.cpp
+NODEP_CPP_SOCK_DGR=\
+ ".\ace\SOCK_Dgram.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\SOCK_Dgram.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_Connector.cpp
+NODEP_CPP_SOCK_C=\
+ ".\ace\SOCK_Connector.h"\
+ ".\ace\Handle_Set.h"\
+ ".\ace\INET_Addr.h"\
+
+
+"$(INTDIR)\SOCK_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_CODgram.cpp
+NODEP_CPP_SOCK_CO=\
+ ".\ace\SOCK_CODgram.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\SOCK_CODgram.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK_Acceptor.cpp
+NODEP_CPP_SOCK_A=\
+ ".\ace\SOCK_Acceptor.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\SOCK_Acceptor.i"\
+
+
+"$(INTDIR)\SOCK_Acceptor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Signal.cpp
+NODEP_CPP_SIGNA=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Signal.h"\
+ ".\ace\Signal.i"\
+
+
+"$(INTDIR)\Signal.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Shared_Object.cpp
+NODEP_CPP_SHARE=\
+ ".\ace\Shared_Object.h"\
+ ".\ace\Shared_Object.i"\
+
+
+"$(INTDIR)\Shared_Object.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Shared_Memory_SV.cpp
+NODEP_CPP_SHARED=\
+ ".\ace\Shared_Memory_SV.h"\
+ ".\ace\Shared_Memory_SV.i"\
+
+
+"$(INTDIR)\Shared_Memory_SV.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Shared_Memory_MM.cpp
+NODEP_CPP_SHARED_=\
+ ".\ace\Shared_Memory_MM.h"\
+ ".\ace\Shared_Memory_MM.i"\
+
+
+"$(INTDIR)\Shared_Memory_MM.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Service_Repository.cpp
+NODEP_CPP_SERVI=\
+ ".\ace\Service_Repository.h"\
+ ".\ace\Service_Repository.i"\
+
+
+"$(INTDIR)\Service_Repository.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Service_Record.cpp
+NODEP_CPP_SERVIC=\
+ ".\ace\Service_Record.h"\
+ ".\ace\Service_Record.i"\
+
+
+"$(INTDIR)\Service_Record.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Service_Object.cpp
+NODEP_CPP_SERVICE=\
+ ".\ace\Service_Object.h"\
+ ".\ace\Service_Object.i"\
+
+
+"$(INTDIR)\Service_Object.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Service_Manager.cpp
+NODEP_CPP_SERVICE_=\
+ ".\ace\Get_Opt.h"\
+ ".\ace\Service_Repository.h"\
+ ".\ace\Service_Config.h"\
+ ".\ace\Service_Manager.h"\
+ ".\ace\Reactor.h"\
+ ".\ace\Service_Manager.i"\
+
+
+"$(INTDIR)\Service_Manager.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Service_Main.cpp
+NODEP_CPP_SERVICE_M=\
+ ".\ace\Service_Config.h"\
+
+
+"$(INTDIR)\Service_Main.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Service_Config.cpp
+NODEP_CPP_SERVICE_C=\
+ ".\ace\Svc_Conf.h"\
+ ".\ace\Get_Opt.h"\
+ ".\ace\ARGV.h"\
+ ".\ace\Malloc.h"\
+ ".\ace\Service_Manager.h"\
+ ".\ace\Service_Repository.h"\
+ ".\ace\Service_Record.h"\
+ ".\ace\Set.h"\
+ ".\ace\Auto_Ptr.h"\
+ ".\ace\Service_Config.h"\
+ ".\ace\Service_Config.i"\
+
+
+"$(INTDIR)\Service_Config.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Remote_Tokens.cpp
+NODEP_CPP_REMOT=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Remote_Tokens.h"\
+ ".\ace\Singleton.h"\
+ ".\ace\Remote_Tokens.i"\
+
+
+"$(INTDIR)\Remote_Tokens.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Remote_Name_Space.cpp
+NODEP_CPP_REMOTE=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Remote_Name_Space.h"\
+
+
+"$(INTDIR)\Remote_Name_Space.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Read_Buffer.cpp
+NODEP_CPP_READ_=\
+ ".\ace\Read_Buffer.h"\
+ ".\ace\Service_Config.h"\
+
+
+"$(INTDIR)\Read_Buffer.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Reactor.cpp
+NODEP_CPP_REACT=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Synch_T.h"\
+ ".\ace\SOCK_Acceptor.h"\
+ ".\ace\SOCK_Connector.h"\
+ ".\ace\Reactor.h"\
+
+
+"$(INTDIR)\Reactor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Profile_Timer.cpp
+NODEP_CPP_PROFI=\
+ ".\ace\Profile_Timer.h"\
+ ".\ace\Profile_Timer.i"\
+
+
+"$(INTDIR)\Profile_Timer.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Process_Manager.cpp
+NODEP_CPP_PROCE=\
+ ".\ace\Process_Manager.h"\
+ ".\ace\Process_Manager.i"\
+
+
+"$(INTDIR)\Process_Manager.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Pipe.cpp
+NODEP_CPP_PIPE_=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\SOCK_Acceptor.h"\
+ ".\ace\SOCK_Connector.h"\
+ ".\ace\Pipe.h"\
+
+
+"$(INTDIR)\Pipe.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Parse_Node.cpp
+NODEP_CPP_PARSE=\
+ ".\ace\Service_Config.h"\
+ ".\ace\Service_Repository.h"\
+ ".\ace\Task.h"\
+ ".\ace\Parse_Node.h"\
+ ".\ace\Parse_Node.i"\
+
+
+"$(INTDIR)\Parse_Node.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\OS.cpp
+NODEP_CPP_OS_CP=\
+ ".\ace\OS.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\ARGV.h"\
+ ".\ace\OS.i"\
+ ".\ace\Synch.h"\
+ ".\ace\Set.h"\
+
+
+"$(INTDIR)\OS.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Obstack.cpp
+NODEP_CPP_OBSTA=\
+ ".\ace\Obstack.h"\
+
+
+"$(INTDIR)\Obstack.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Naming_Context.cpp
+NODEP_CPP_NAMIN=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Get_Opt.h"\
+ ".\ace\Naming_Context.h"\
+ ".\ace\Remote_Name_Space.h"\
+ ".\ace\Local_Name_Space.h"\
+
+
+"$(INTDIR)\Naming_Context.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Name_Space.cpp
+NODEP_CPP_NAME_=\
+ ".\ace\Name_Space.h"\
+
+
+"$(INTDIR)\Name_Space.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Name_Request_Reply.cpp
+NODEP_CPP_NAME_R=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Name_Request_Reply.h"\
+
+
+"$(INTDIR)\Name_Request_Reply.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Name_Proxy.cpp
+NODEP_CPP_NAME_P=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Name_Proxy.h"\
+
+
+"$(INTDIR)\Name_Proxy.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Multiplexor.cpp
+NODEP_CPP_MULTI=\
+ ".\ace\Multiplexor.h"\
+ ".\ace\Multiplexor.i"\
+
+
+"$(INTDIR)\Multiplexor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Message_Block.cpp
+NODEP_CPP_MESSA=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Message_Block.h"\
+ ".\ace\Message_Block.i"\
+
+
+"$(INTDIR)\Message_Block.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Memory_Pool.cpp
+NODEP_CPP_MEMOR=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Memory_Pool.h"\
+ ".\ace\Memory_Pool.i"\
+
+
+"$(INTDIR)\Memory_Pool.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Mem_Map.cpp
+NODEP_CPP_MEM_M=\
+ ".\ace\Mem_Map.h"\
+ ".\ace\Mem_Map.i"\
+
+
+"$(INTDIR)\Mem_Map.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Malloc.cpp
+NODEP_CPP_MALLO=\
+ ".\ace\Malloc.h"\
+ ".\ace\Malloc.i"\
+
+
+"$(INTDIR)\Malloc.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\LSOCK_Stream.cpp
+NODEP_CPP_LSOCK=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\LSOCK_Stream.h"\
+
+
+"$(INTDIR)\LSOCK_Stream.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\LSOCK_Dgram.cpp
+NODEP_CPP_LSOCK_=\
+ ".\ace\LSOCK_Dgram.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\LSOCK_Dgram.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\LSOCK_Connector.cpp
+NODEP_CPP_LSOCK_C=\
+ ".\ace\LSOCK_Connector.h"\
+
+
+"$(INTDIR)\LSOCK_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\LSOCK_CODgram.cpp
+NODEP_CPP_LSOCK_CO=\
+ ".\ace\LSOCK_CODgram.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\LSOCK_CODgram.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\LSOCK_Acceptor.cpp
+NODEP_CPP_LSOCK_A=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\LSOCK_Acceptor.h"\
+ ".\ace\LSOCK_Acceptor.i"\
+
+
+"$(INTDIR)\LSOCK_Acceptor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\LSOCK.cpp
+NODEP_CPP_LSOCK_CP=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\LSOCK.h"\
+
+
+"$(INTDIR)\LSOCK.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Log_Record.cpp
+NODEP_CPP_LOG_R=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Log_Record.h"\
+
+
+"$(INTDIR)\Log_Record.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Log_Msg.cpp
+NODEP_CPP_LOG_M=\
+ ".\ace\config.h"\
+ ".\ace\ACE.h"\
+ ".\ace\Thread.h"\
+ ".\ace\Synch.h"\
+ ".\ace\Log_Msg.h"\
+ ".\ace\SPIPE_Connector.h"\
+ ".\ace\FIFO_Send_Msg.h"\
+
+
+"$(INTDIR)\Log_Msg.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Local_Tokens.cpp
+NODEP_CPP_LOCAL=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Thread.h"\
+ ".\ace\Local_Tokens.h"\
+ ".\ace\Token_Manager.h"\
+ ".\ace\Local_Tokens.i"\
+
+
+"$(INTDIR)\Local_Tokens.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Local_Name_Space.cpp
+NODEP_CPP_LOCAL_=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\ACE.h"\
+ ".\ace\Local_Name_Space.h"\
+
+
+"$(INTDIR)\Local_Name_Space.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\IPC_SAP.cpp
+NODEP_CPP_IPC_S=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\IPC_SAP.h"\
+
+
+"$(INTDIR)\IPC_SAP.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\IO_SAP.cpp
+NODEP_CPP_IO_SA=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\IO_SAP.h"\
+
+
+"$(INTDIR)\IO_SAP.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\IO_Cntl_Msg.cpp
+
+"$(INTDIR)\IO_Cntl_Msg.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\INET_Addr.cpp
+NODEP_CPP_INET_=\
+ ".\ace\INET_Addr.h"\
+ ".\ace\INET_Addr.i"\
+
+
+"$(INTDIR)\INET_Addr.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\High_Res_Timer.cpp
+NODEP_CPP_HIGH_=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\High_Res_Timer.h"\
+ ".\ace\High_Res_Timer.i"\
+
+
+"$(INTDIR)\High_Res_Timer.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Handle_Set.cpp
+NODEP_CPP_HANDL=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Handle_Set.h"\
+ ".\ace\Handle_Set.i"\
+
+
+"$(INTDIR)\Handle_Set.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Get_Opt.cpp
+NODEP_CPP_GET_O=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Get_Opt.h"\
+ ".\ace\Get_Opt.i"\
+
+
+"$(INTDIR)\Get_Opt.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FILE_IO.cpp
+NODEP_CPP_FILE_=\
+ ".\ace\FILE_IO.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\FILE_IO.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FILE_Connector.cpp
+NODEP_CPP_FILE_C=\
+ ".\ace\FILE_Connector.h"\
+
+
+"$(INTDIR)\FILE_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FILE_Addr.cpp
+NODEP_CPP_FILE_A=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\FILE_Addr.h"\
+ ".\ace\FILE_Addr.i"\
+
+
+"$(INTDIR)\FILE_Addr.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FILE.cpp
+NODEP_CPP_FILE_CP=\
+ ".\ace\FILE.h"\
+
+
+"$(INTDIR)\FILE.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FIFO_Send_Msg.cpp
+NODEP_CPP_FIFO_=\
+ ".\ace\FIFO_Send_Msg.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\FIFO_Send_Msg.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FIFO_Send.cpp
+NODEP_CPP_FIFO_S=\
+ ".\ace\FIFO_Send.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\FIFO_Send.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FIFO_Recv_Msg.cpp
+NODEP_CPP_FIFO_R=\
+ ".\ace\FIFO_Recv_Msg.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\FIFO_Recv_Msg.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FIFO_Recv.cpp
+NODEP_CPP_FIFO_RE=\
+ ".\ace\FIFO_Recv.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\FIFO_Recv.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Event_Handler.cpp
+NODEP_CPP_EVENT=\
+ ".\ace\Event_Handler.h"\
+ ".\ace\Message_Block.h"\
+ ".\ace\Event_Handler.i"\
+
+
+"$(INTDIR)\Event_Handler.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Dynamic.cpp
+NODEP_CPP_DYNAM=\
+ ".\ace\Dynamic.h"\
+ ".\ace\Dynamic.i"\
+
+
+"$(INTDIR)\Dynamic.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Dump.cpp
+NODEP_CPP_DUMP_=\
+ ".\ace\Dump.h"\
+
+
+"$(INTDIR)\Dump.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\DEV_IO.cpp
+NODEP_CPP_DEV_I=\
+ ".\ace\DEV_IO.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\DEV_IO.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\DEV_Connector.cpp
+NODEP_CPP_DEV_C=\
+ ".\ace\DEV_Connector.h"\
+
+
+"$(INTDIR)\DEV_Connector.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\DEV_Addr.cpp
+NODEP_CPP_DEV_A=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\DEV_Addr.h"\
+ ".\ace\DEV_Addr.i"\
+
+
+"$(INTDIR)\DEV_Addr.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\DEV.cpp
+NODEP_CPP_DEV_CP=\
+ ".\ace\DEV.h"\
+
+
+"$(INTDIR)\DEV.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Date_Time.cpp
+NODEP_CPP_DATE_=\
+ ".\ace\Date_Time.h"\
+
+
+"$(INTDIR)\Date_Time.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\CORBA_Handler.cpp
+NODEP_CPP_CORBA=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\CORBA_Handler.h"\
+ ".\ace\CORBA_Handler.i"\
+
+
+"$(INTDIR)\CORBA_Handler.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ARGV.cpp
+NODEP_CPP_ARGV_=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\ARGV.h"\
+ ".\ace\ARGV.i"\
+
+
+"$(INTDIR)\ARGV.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Addr.cpp
+NODEP_CPP_ADDR_=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Addr.h"\
+ ".\ace\Addr.i"\
+
+
+"$(INTDIR)\Addr.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ACE.cpp
+NODEP_CPP_ACE_C=\
+ ".\ace\IPC_SAP.h"\
+ ".\ace\Time_Value.h"\
+ ".\ace\Handle_Set.h"\
+ ".\ace\ACE.h"\
+ ".\ace\Thread_Manager.h"\
+ ".\ace\Reactor.h"\
+
+
+"$(INTDIR)\ACE.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\SOCK.cpp
+NODEP_CPP_SOCK_CP=\
+ ".\ace\SOCK.h"\
+ ".\ace\Log_Msg.h"\
+
+
+"$(INTDIR)\SOCK.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\FIFO.cpp
+NODEP_CPP_FIFO_C=\
+ ".\ace\FIFO.h"\
+ ".\ace\FIFO.i"\
+
+
+"$(INTDIR)\FIFO.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Proactor.cpp
+NODEP_CPP_PROAC=\
+ ".\ace\Proactor.h"\
+ ".\ace\Proactor.i"\
+
+
+"$(INTDIR)\Proactor.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ReactorEx.cpp
+NODEP_CPP_REACTO=\
+ ".\ace\ReactorEx.h"\
+ ".\ace\ReactorEx.i"\
+
+
+"$(INTDIR)\ReactorEx.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Token_Invariants.cpp
+NODEP_CPP_TOKEN_I=\
+ ".\ace\Log_Msg.h"\
+ ".\ace\Token_Invariants.h"\
+ ".\ace\Token_Invariants.i"\
+
+
+"$(INTDIR)\Token_Invariants.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\Process.cpp
+NODEP_CPP_PROCES=\
+ ".\ace\Process.h"\
+ ".\ace\Process.i"\
+
+
+"$(INTDIR)\Process.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\TTY_IO.cpp
+NODEP_CPP_TTY_I=\
+ ".\ace\TTY_IO.h"\
+
+
+"$(INTDIR)\TTY_IO.obj" : $(SOURCE) "$(INTDIR)"
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/ace/ace.mdp b/ace/ace.mdp Binary files differnew file mode 100644 index 00000000000..ffa58663909 --- /dev/null +++ b/ace/ace.mdp diff --git a/ace/config-aix-3.2.5.h b/ace/config-aix-3.2.5.h new file mode 100644 index 00000000000..bdf3593f176 --- /dev/null +++ b/ace/config-aix-3.2.5.h @@ -0,0 +1,47 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for AIX 3.2.5 +// with xlC. Thanks to Bob Olson <olson@mcs.anl.gov> for this. + +/*#define ACE_HAS_PTHREADS*/ + +#define MAXNAMELEN 1024 + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +#define ACE_HAS_TEMPLATE_TYPEDEFS + +#define ACE_HAS_STRERROR + +#define ACE_HAS_SIG_ATOMIC_T + +#define ACE_HAS_SSIZE_T + +#define ACE_HAS_CPLUSPLUS_HEADERS + +#define ACE_HAS_POLL + +#define ACE_HAS_POSIX_NONBLOCK + +#define ACE_HAS_AIX_GETTIMEOFDAY + +#define ACE_HAS_NO_SYSCALL_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Compiler/platform uses old malloc()/free() prototypes (ugh). +#define ACE_HAS_OLD_MALLOC + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +/*#define ACE_HAS_STREAMS*/ diff --git a/ace/config-aix-4.1.x.h b/ace/config-aix-4.1.x.h new file mode 100644 index 00000000000..0f27126b334 --- /dev/null +++ b/ace/config-aix-4.1.x.h @@ -0,0 +1,105 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for HP +// platforms running AIX 4.1.x. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Compiling for AIX. +#define AIX +#define _BSD 43 +#define ACE_HAS_UNION_WAIT +#define ACE_HAS_MULTICAST +#define ACE_HAS_TID_T +#define ACE_HAS_SIGWAIT +#define ACE_HAS_H_ERRNO +#define ACE_LACKS_THREAD_PROCESS_SCOPING +#define ACE_LACKS_THREAD_STACK_ADDR +#define ACE_LACKS_CONDATTR_PSHARED +#define ACE_HAS_SIN_LEN +#define ACE_HAS_SYSV_IPC +#define ACE_HAS_STRUCT_NETDB_DATA +#define ACE_HAS_ALLOCA +#define ACE_HAS_REENTRANT_FUNCTIONS +#define ACE_HAS_SYSV_IPC +#define ACE_HAS_TLI +#define ACE_HAS_TLI_PROTOTYPES +#define ACE_HAS_TIUSER_H +#define ACE_TEMPLATES_REQUIRE_PRAGMA +#define ACE_HAS_THREAD_SPECIFIC_STORAGE +#define ACE_HAS_AUTOMATIC_INIT_FINI +#define ACE_HAS_CHARPTR_DL +#define ACE_HAS_SVR4_DYNAMIC_LINKING +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME +#define ACE_HAS_THREADS +#define ACE_MT_SAFE +#define ACE_HAS_UTIME +#define ACE_HAS_SELECT_H + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// This environment requires this thing +#define _BSD_INCLUDES +#define COMPAT_43 + +// Compiler supports the getrusage() system call +#define ACE_HAS_GETRUSAGE + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform defines the sig_atomic_t typedef +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Compiler supports stropts.h +#define ACE_HAS_STREAMS +// #define ACE_HAS_STREAM_PIPES + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// EYE the include file is there + +// AIX bzero() +#define ACE_HAS_STRINGS + +// ??? has the berkeley stuff +// #define ACE_HAS_SUNOS4_GETTIMEOFDAY +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Note, this only works if the flag is set above! +#define ACE_HAS_GETRUSAGE + +// EYE assume it does for now. +#define ACE_HAS_DCETHREADS +#define ACE_PTHREADS_MAP + +// include there +#define ACE_HAS_TIMOD_H +#define ACE_HAS_TIUSER_H + +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ +#define ACE_HAS_STRBUF_T + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-hpux-10.x-g++.h b/ace/config-hpux-10.x-g++.h new file mode 100644 index 00000000000..2930a01a058 --- /dev/null +++ b/ace/config-hpux-10.x-g++.h @@ -0,0 +1,99 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for HP +// platforms running HP/UX 10.x using G++. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Compiling for HPUX. +#if !defined (HPUX) +#define HPUX +#endif /* HPUX */ + +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES +// Must specialize templates due to G++'s lame parameterized type +// support... I added this Afara +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +#define ACE_LACKS_SYSCALL +#define ACE_LACKS_STRRECVFD +#define ACE_HAS_POSIX_TIME + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Fixes a problem with HP/UX not wrapping the mmap(2) header files +// with extern "C". +#define ACE_HAS_BROKEN_MMAP_H + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Header files lack t_errno for ACE_TLI. +#define ACE_LACKS_T_ERRNO + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform defines the sig_atomic_t typedef +#define ACE_HAS_SIG_ATOMIC_T + +// ACE supports POSIX Pthreads. +//#define ACE_HAS_DCETHREADS //changed by Afara 09/24/96 + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// ??? +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// HP/UX has an undefined syscall for GETRUSAGE... +#define ACE_HAS_SYSCALL_GETRUSAGE + +// Note, this only works if the flag is set above! +#define ACE_HAS_GETRUSAGE + +// Platform uses int for select() rather than fd_set. +#define ACE_SELECT_USES_INT + +// Platform has the XLI version of ACE_TLI. +// #define ACE_HAS_XLI + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-hpux-10.x.h b/ace/config-hpux-10.x.h new file mode 100644 index 00000000000..cdfad30891e --- /dev/null +++ b/ace/config-hpux-10.x.h @@ -0,0 +1,110 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for HP +// platforms running HP/UX 10.x. For using HP C++ compiler with +// templates you should have patch PHSS_6246. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Compiling for HPUX. +#if !defined (HPUX) +#define HPUX +#endif /* HPUX */ + +#define _HPUX_SOURCE +#include <sys/stdsyms.h> +#include <sched.h> // pthread.h doesn't include this + +#define ACE_LACKS_SYSCALL +#define ACE_HAS_POSIX_TIME + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Fixes a problem with HP/UX not wrapping the mmap(2) header files +// with extern "C". +#define ACE_HAS_BROKEN_MMAP_H + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Header files lack t_errno for ACE_TLI. +#define ACE_LACKS_T_ERRNO + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform defines the sig_atomic_t typedef +#define ACE_HAS_SIG_ATOMIC_T + +#define ACE_HAS_THREADS +#define ACE_HAS_PTHREADS +#define ACE_MT_SAFE +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_SETKIND_NP +#define ACE_LACKS_CONDATTR_PSHARED +#define ACE_LACKS_SI_ADDR +#define ACE_LACKS_SETDETACH // new +#define ACE_LACKS_KEYDELETE // new +#define ACE_LACKS_THREAD_PROCESS_SCOPING +#define ACE_LACKS_THREAD_STACK_ADDR + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// ??? +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// HP/UX has an undefined syscall for GETRUSAGE... +#define ACE_HAS_SYSCALL_GETRUSAGE + +// Note, this only works if the flag is set above! +#define ACE_HAS_GETRUSAGE + +// Platform uses int for select() rather than fd_set. +#define ACE_SELECT_USES_INT + +// Platform has the XLI version of ACE_TLI. +// #define ACE_HAS_XLI + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-hpux-9.x-orbix.h b/ace/config-hpux-9.x-orbix.h new file mode 100644 index 00000000000..0cf71f2f3ee --- /dev/null +++ b/ace/config-hpux-9.x-orbix.h @@ -0,0 +1,89 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for HP +// platforms running HP/UX 9.x. Dave added Orbix stuff + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Compiling for HPUX. +#if !defined (HPUX) +#define HPUX +#endif /* HPUX */ + +// ************* HERE IS THE ORBIX STUFF - Dave 4/2/96 +#define ACE_HAS_ORBIX + +#define ACE_LACKS_SYSCALL +#define ACE_LACKS_STRRECVFD + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Fixes a problem with HP/UX not wrapping the mmap(2) header files +// with extern "C". +#define ACE_HAS_BROKEN_MMAP_H + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Header files lack t_errno for ACE_TLI. +#define ACE_LACKS_T_ERRNO + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform defines the sig_atomic_t typedef +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// ??? +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// HP/UX has an undefined syscall for GETRUSAGE... +#define ACE_HAS_SYSCALL_GETRUSAGE + +// Note, this only works if the flag is set above! +#define ACE_HAS_GETRUSAGE + +// Platform uses int for select() rather than fd_set. +// Dave 4/2/96 took this out. It appears that HP -can- use fd_set for int +// But time.h has a prototype defined so that int must be used ! so it goes +// back in +#define ACE_SELECT_USES_INT + +// Platform has prototypes for ACE_TLI. +//#define ACE_HAS_TLI_PROTOTYPES +// Platform has the XLI version of ACE_TLI. +// #define ACE_HAS_XLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-hpux-9.x.h b/ace/config-hpux-9.x.h new file mode 100644 index 00000000000..57a90f3cb59 --- /dev/null +++ b/ace/config-hpux-9.x.h @@ -0,0 +1,83 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for HP platforms running HP/UX 9.x. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Compiling for HPUX. +#if !defined (HPUX) +#define HPUX +#endif /* HPUX */ + +#define ACE_LACKS_SYSCALL +#define ACE_LACKS_STRRECVFD + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Fixes a problem with HP/UX not wrapping the mmap(2) header files +// with extern "C". +#define ACE_HAS_BROKEN_MMAP_H + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Header files lack t_errno for ACE_TLI. +#define ACE_LACKS_T_ERRNO + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform defines the sig_atomic_t typedef +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// ??? +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// HP/UX has an undefined syscall for GETRUSAGE... +#define ACE_HAS_SYSCALL_GETRUSAGE + +// Note, this only works if the flag is set above! +#define ACE_HAS_GETRUSAGE + +// Platform uses int for select() rather than fd_set. +#define ACE_SELECT_USES_INT + +// Platform has prototypes for ACE_TLI. +//#define ACE_HAS_TLI_PROTOTYPES +// Platform has the XLI version of ACE_TLI. +// #define ACE_HAS_XLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-irix5.2.h b/ace/config-irix5.2.h new file mode 100644 index 00000000000..3b729019f05 --- /dev/null +++ b/ace/config-irix5.2.h @@ -0,0 +1,62 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for the SGI +// Indigo2EX running Irix 5.2 platform using the gcc v2.6.x compiler +// and libg++ v2.6.x. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Platform supports STREAM pipes (note that this is disabled by +// default, see the manual page on pipe(2) to find out how to enable +// it). +//#define ACE_HAS_STREAM_PIPES + +#define ACE_HAS_SIGWAIT + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform requires void * for mmap(). +#define ACE_HAS_VOIDPTR_MMAP + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +#define IRIX5 +#define ACE_HAS_ALLOCA +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H +#define ACE_HAS_BSTRING +#define ACE_HAS_GETRUSAGE +#define ACE_HAS_POSIX_NONBLOCK +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME +#define ACE_HAS_CPLUSPLUS_HEADERS +#define ACE_HAS_POLL +#define ACE_HAS_PROC_FS +#define ACE_HAS_RTLD_LAZY_V +#define ACE_HAS_SIG_ATOMIC_T +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T +#define ACE_HAS_STREAMS +#define ACE_HAS_SSIZE_T +#define ACE_HAS_STRERROR +#define ACE_HAS_STRBUF_T +#define ACE_HAS_SVR4_DYNAMIC_LINKING +#define ACE_HAS_SVR4_SIGNAL_T +#define ACE_HAS_SYS_SIGLIST +#define ACE_HAS_SYS_FILIO_H +#define ACE_HAS_SEMUN +#define ACE_PAGE_SIZE 4096 + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-irix5.3-g++.h b/ace/config-irix5.3-g++.h new file mode 100644 index 00000000000..7c23f36a848 --- /dev/null +++ b/ace/config-irix5.3-g++.h @@ -0,0 +1,121 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for the SGI +// Indigo2EX running Irix 5.3 platform using the GNU C++ Compiler + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define IRIX5 +#define ACE_HAS_SIGWAIT + +#define ACE_TEMPLATES_REQUIRE_SOURCE + +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform requires void * for mmap(). +#define ACE_HAS_VOIDPTR_MMAP + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// IRIX5 needs to define bzero() in this odd file <bstring.h> +#define ACE_HAS_BSTRING + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Denotes that IRIX 5.3 has second argument to gettimeofday() +// which is variable ... +#define ACE_HAS_IRIX_GETTIMEOFDAY + +// Denotes that GNU has cstring.h as standard +// which redefines memchr() +#define ACE_HAS_GNU_CSTRING_H + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes (note that this is disabled by +// default, see the manual page on pipe(2) to find out how to enable +// it). +// #define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_IRIX_53_SIGNALS + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-irix5.3-sgic++.h b/ace/config-irix5.3-sgic++.h new file mode 100644 index 00000000000..2a4781e320e --- /dev/null +++ b/ace/config-irix5.3-sgic++.h @@ -0,0 +1,118 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for the SGI Indigo2EX running Irix 5.3 platform using +// the SGI C++ Compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define IRIX5 + +#define ACE_NEEDS_SYSTIME_H +#define ACE_HAS_SIGWAIT + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform requires void * for mmap(). +#define ACE_HAS_VOIDPTR_MMAP + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// IRIX5 needs to define bzero() in this odd file <bstring.h> +#define ACE_HAS_BSTRING + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Denotes that IRIX 5.3 has second argument to gettimeofday() +// which is variable ... +#define ACE_HAS_IRIX_GETTIMEOFDAY + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// No multi-threading so use poll() call +// - for easier debugging, if nothing else +// #define ACE_USE_POLL + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes (note that this is disabled by +// default, see the manual page on pipe(2) to find out how to enable +// it). +// #define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_IRIX_53_SIGNALS + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-irix6.2-sgic++.h b/ace/config-irix6.2-sgic++.h new file mode 100644 index 00000000000..8c065491dd3 --- /dev/null +++ b/ace/config-irix6.2-sgic++.h @@ -0,0 +1,151 @@ +/* -*- C++ -*- */ +// $Id$ + +// 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 + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_IRIX62_THREADS + +// Needed for the threading stuff? +#include <sched.h> +#include <task.h> +#define PTHREAD_MIN_PRIORITY PX_PRIO_MIN +#define PTHREAD_MAX_PRIORITY PX_PRIO_MAX + +// ACE supports threads. +#define ACE_HAS_THREADS + +//Sockets may be called in multi-threaded programs +#define ACE_HAS_MT_SAFE_SOCKETS + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Compile using multi-thread libraries +#define ACE_MT_SAFE + +// Platform supports the tid_t type (e.g., AIX and Irix 6.2) +#define ACE_HAS_TID_T + +// Platform has no implementation of pthread_condattr_setpshared(), +// even though it supports pthreads! (like Irix 6.2) +#define ACE_LACKS_CONDATTR_PSHARED + +// IRIX 6.2 supports some variant of POSIX Pthreads, is it stock DCE? +#define ACE_HAS_PTHREADS + +// Platform/compiler has the sigwait(2) prototype +#define ACE_HAS_SIGWAIT + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform requires void * for mmap(). +#define ACE_HAS_VOIDPTR_MMAP + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Irix needs to define bzero() in this odd file <bstring.h> +#define ACE_HAS_BSTRING + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Denotes that Irix has second argument to gettimeofday() which is +// variable (...) +#define ACE_HAS_IRIX_GETTIMEOFDAY + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// No multi-threading so use poll() call +// - for easier debugging, if nothing else +// #define ACE_USE_POLL + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes (note that this is disabled by +// default, see the manual page on pipe(2) to find out how to enable +// it). +// #define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-linux-pthread.h b/ace/config-linux-pthread.h new file mode 100644 index 00000000000..942510e4a17 --- /dev/null +++ b/ace/config-linux-pthread.h @@ -0,0 +1,99 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for Linux +// platforms using GNU C++ and the MIT threads package. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Fixes a problem with new versions of Linux... +#ifndef msg_accrights +#undef msg_control +#define msg_accrights msg_control +#endif + +#ifndef msg_accrightslen +#undef msg_controllen +#define msg_accrightslen msg_controllen +#endif + +#define ACE_HAS_POSIX_TIME +#define ACE_LACKS_STRRECVFD + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Platforms lacks UNIX domain sockets. +//#define ACE_LACKS_UNIX_DOMAIN_SOCKETS + +// Compiler/platform supports alloca(). +#define ACE_HAS_ALLOCA + +//#define ACE_LACKS_SENDMSG +//#define ACE_LACKS_RECVMSG +#define ACE_LACKS_MSYNC +#define ACE_LACKS_MADVISE + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#define ACE_HAS_SUNOS4_GETTIMEOFDAY +#define LINUX 1.2.10 + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Linux defines struct msghdr in /usr/include/socket.h +#define ACE_HAS_MSG + +// TDN - adapted from file for SunOS4 platforms using the GNU g++ compiler +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE + +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Yes, we do have threads. +#define ACE_HAS_THREADS +// And they're even POSIX pthreads (MIT implementation) +#define ACE_HAS_PTHREADS +#define ACE_HAS_SIGWAIT +#define ACE_LACKS_CONDATTR_PSHARED + +// To use pthreads on Linux you'll need to use the MIT version, for +// now... +#define _MIT_POSIX_THREADS 1 +#include <pthread/mit/pthread.h> + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-linux.h b/ace/config-linux.h new file mode 100644 index 00000000000..fb4d787fc47 --- /dev/null +++ b/ace/config-linux.h @@ -0,0 +1,91 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for Linux +// platforms using GNU C++. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Do we really need this #define here? +#define LINUX 1.2.10 + +// Fixes a problem with new versions of Linux... +#ifndef msg_accrights +#undef msg_control +#define msg_accrights msg_control +#endif + +#ifndef msg_accrightslen +#undef msg_controllen +#define msg_accrightslen msg_controllen +#endif + +// You may need to undefine these for older versions of Linux. +//#define ACE_LACKS_SENDMSG +//#define ACE_LACKS_RECVMSG + +#define ACE_HAS_POSIX_TIME +#define ACE_LACKS_STRRECVFD + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Platforms lacks UNIX domain sockets. +//#define ACE_LACKS_UNIX_DOMAIN_SOCKETS + +// Compiler/platform supports alloca(). +#define ACE_HAS_ALLOCA + +#define ACE_LACKS_MSYNC +#define ACE_LACKS_MADVISE + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Linux defines struct msghdr in /usr/include/socket.h +#define ACE_HAS_MSG + +// TDN - adapted from file for SunOS4 platforms using the GNU g++ compiler +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE + +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-m88k.h b/ace/config-m88k.h new file mode 100644 index 00000000000..f2c2222a17c --- /dev/null +++ b/ace/config-m88k.h @@ -0,0 +1,223 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for Motorolla 88k SVR4 platforms +// using pthreads from Florida State (ACE_HAS_FSU_PTHREADS) + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#if !defined (m88k) +#define m88k +#endif + +extern "C" void pthread_init(); + +#define PTHREAD_STACK_MIN 1024 + +#if !defined (IP_ADD_MEMBERSHIP) +#define IP_ADD_MEMBERSHIP 0x13 +#endif // m88k + +#if !defined (IP_DROP_MEMBERSHIP) +#define IP_DROP_MEMBERSHIP 0x14 +#endif // m88k + +struct sched_param +{ + int sched_priority; + int prio; +}; + +// This seems to be necessary for m88k. +struct ip_mreq +{ + struct in_addr imr_multiaddr; // IP multicast address of the group + struct in_addr imr_interface; // local IP address of the interface +}; + +#if !defined (ACE_HAS_FSU_PTHREADS) +#define ACE_HAS_FSU_PTHREADS +#endif + +// Added for compilation on the m88k +#if defined (m88k) +#define ACE_LACKS_T_ERRNO +#define ACE_LACKS_MADVISE +#define ACE_HAS_GNU_CSTRING_H +#define ACE_TEMPLATES_REQUIRE_SOURCE +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES +#endif // m88k + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Sun has the wrong prototype for sendmsg. +#define ACE_HAS_BROKEN_SENDMSG + +// The SunOS 5.x version of rand_r is inconsistent with the header files... +#define ACE_HAS_BROKEN_RANDR + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library. +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +#if !defined (ACE_HAS_FSU_PTHREADS) +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS +#endif // ACE_HAS_FSU_PTHREADS + +// Platform has terminal ioctl flags like TCGETS and TCSETS. +#define ACE_HAS_TERM_IOCTLS + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +#if !defined (m88k) +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER +#endif // m88k + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +#if !defined (m88k) +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H +#endif // m88k + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +#if !defined (m88k) +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T +#endif // m88k + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +#if !defined (m88k) +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST +#endif // m88k + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +#if !defined (m88k) +// Platform supports Solaris threads. +#define ACE_HAS_STHREADS +#else +#define ACE_HAS_PTHREADS +#endif // m88k + +// Platform supports threads. +#define ACE_HAS_THREADS + +#if defined (ACE_HAS_FSU_PTHREADS) +#define ACE_LACKS_THREAD_STACK_ADDR +#endif // ACE_HAS_FSU_PTHREADS + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Reactor detects deadlock +// #define ACE_REACTOR_HAS_DEADLOCK_DETECTION + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-osf1-3.2.h b/ace/config-osf1-3.2.h new file mode 100644 index 00000000000..2bb2ba7ee0a --- /dev/null +++ b/ace/config-osf1-3.2.h @@ -0,0 +1,165 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for OSF1 3.2 +// platforms with the DEC 5.1 C++ compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_PTHREAD_MUTEXATTR_CREATE +#define ACE_HAS_PTHREAD_MUTEXATTR_DELETE + +#define ACE_HAS_BROKEN_MSG_H +#define ACE_LACKS_SYSV_MSQ_PROTOS + +// Platform supports <sys/procfs.h> +#define ACE_HAS_PROC_FS + +// Platform supports tid_t +#define ACE_HAS_TID_T + +// Platform lacks support for shared condition variables +#define ACE_LACKS_CONDATTR_PSHARED + +// Platform lacks support for stack address information +#define ACE_LACKS_THREAD_STACK_ADDR + +// Platform lacks thread process scoping +#define ACE_LACKS_THREAD_PROCESS_SCOPING + +// Platform has non-POSIX setkind and other functions. +#define ACE_HAS_SETKIND_NP +#define ACE_HAS_PTHREAD_T + +// Platform defines MAP_FAILED as a long constant. +#define ACE_HAS_LONG_MAP_FAILED + +// Platform's implementation of sendmsg() has a non-const msgheader parameter. +#define ACE_HAS_BROKEN_SENDMSG + +// Platform's implementation of writev() has a non-const iovec parameter. +#define ACE_HAS_BROKEN_WRITEV + +// Platform's implementation of setlrmit() has a non-const rlimit parameter. +#define ACE_HAS_BROKEN_SETRLIMIT + +// Compiler has integer overflow problem with bit-shift operations. +#define ACE_HAS_BROKEN_BITSHIFT + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform correctly calls init()/fini(). +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// ACE has no mktemp(). +#define ACE_LACKS_MKTEMP + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports C++ headers +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Platform supports the OSF ACE_TLI timod STREAMS module. +#define ACE_HAS_OSF_TIMOD_H + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME + +// Platform defines struct timespec in <sys/timers.h> +#define ACE_HAS_BROKEN_POSIX_TIME +// #define ACE_HAS_SVR4_TIME + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// ACE supports POSIX Pthreads. +#define ACE_HAS_DCETHREADS + +// Explicit dynamic linking permits "lazy" symbol resolution +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Added 6/13/95, 1 line +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform has ssize_t. +#define ACE_HAS_SSIZE_T + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform has 64bit longs and 32bit ints... +#define ACE_HAS_64BIT_LONGS + +// Platform supports STREAM pipes. +// #define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform support OSF1 gettimeofday +#define ACE_HAS_OSF1_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform has strerror(). +#define ACE_HAS_STRERROR + +// ACE supports threads. +#define ACE_HAS_THREADS + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform supports ACE_TLI timod STREAMS module. +// #define ACE_HAS_TIMOD_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-osf1-4.0.h b/ace/config-osf1-4.0.h new file mode 100644 index 00000000000..784a8673e2f --- /dev/null +++ b/ace/config-osf1-4.0.h @@ -0,0 +1,182 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for the +// Digital UNIX V4.0 platforms with the DEC 5.4 C++ compiler. It is +// configured to use the IEEE Std 1003.1c-1995, POSIX System +// Application Program Interface. An early release Digital UNIX V4.0 +// was used for porting so additional minor changes may be required. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// DJT removed this due to some minor issues related to the +// definitions of timestruc_t and tid_t in procfs.h not sure what +// functionality is lost? Platform supports <sys/procfs.h> +//#define ACE_HAS_PROC_FS + +// Platform defines MAP_FAILED as a long constant. +#define ACE_HAS_LONG_MAP_FAILED + +// DJT 6/10/96 All these broken macro's can now be removed with the +// approporiate ordering of the include files. The Platinum release +// now temporarily supports both forms. Platform's implementation of +// sendmsg() has a non-const msgheader parameter. +#define ACE_HAS_BROKEN_SENDMSG + +// Platform's implementation of writev() has a non-const iovec +// parameter. +#define ACE_HAS_BROKEN_WRITEV + +// Platform's implementation of setlrmit() has a non-const rlimit +// parameter. +#define ACE_HAS_BROKEN_SETRLIMIT + +// Platform supports System V IPC (most versions of UNIX, but not +// Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform correctly calls init()/fini(). +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// ACE has no mktemp(). +//#define ACE_LACKS_MKTEMP + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports C++ headers +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Platform supports the OSF ACE_TLI timod STREAMS module. +#define ACE_HAS_OSF_TIMOD_H + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME + +// Platform defines struct timespec in <sys/timers.h> +// #define ACE_HAS_BROKEN_POSIX_TIME +// DJT added 6/5/96 +// #define ACE_HAS_SVR4_TIME +//#define ACE_HAS_SVR4_TIME + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// DJT modified 6/5/96 +// ACE supports POSIX Pthreads. +//#define ACE_HAS_DCETHREADS +#define ACE_HAS_PTHREADS +// DJT 6/6/96 added +// IEEE Std 1003.1c-1995, POSIX System Application Program Interface +#define ACE_HAS_PTHREADS_1003_DOT_1C + +// Explicit dynamic linking permits "lazy" symbol resolution +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Added 6/13/95, 1 line +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// DJT added 6/7/96 +#define ACE_HAS_SIGWAIT + +// Compiler/platform has ssize_t. +#define ACE_HAS_SSIZE_T + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform has 64bit longs and 32bit ints... +#define ACE_HAS_64BIT_LONGS + +// Platform supports STREAM pipes. +// #define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform support OSF1 gettimeofday +#define ACE_HAS_OSF1_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform has strerror(). +#define ACE_HAS_STRERROR + +// ACE supports threads. +#define ACE_HAS_THREADS + +// DJT modified 6/5/96 +// Platform defines the tid_t structure. +//#define ACE_HAS_TID_T + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform supports ACE_TLI timod STREAMS module. +// #define ACE_HAS_TIMOD_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// DJT added 6/6/96 +#define ACE_LACKS_CONDATTR_PSHARED + +// DJT added 6/7/96 +#define ACE_LACKS_THREAD_STACK_ADDR + +// DJT added 7/10/96 +#define ACE_LACKS_THREAD_PROCESS_SCOPING + +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// DJT modified 6/5/96 +// Defines the page size of the system. +//#define ACE_PAGE_SIZE 4096 +#define ACE_PAGE_SIZE 8192 + +// DJT added 6/6/96 +// uses ctime_r & asctime_r with only two parameters vs. three +#define ACE_HAS_ONLY_TWO_PARAMS_FOR_ASCTIME_R_AND_CTIME_R + +#define ACE_HAS_BROKEN_IF_HEADER + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sco-4.2-nothread.h b/ace/config-sco-4.2-nothread.h new file mode 100644 index 00000000000..428f601493e --- /dev/null +++ b/ace/config-sco-4.2-nothread.h @@ -0,0 +1,105 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for HP platforms running HP/UX 9.x. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Compiling for SCO. +#if !defined (SCO) +#define SCO +#endif /* SCO */ + +#if defined (SCO) && !defined (MAXPATHLEN) +#define MAXPATHLEN 1023 +#endif /* SCO */ + +#define ACE_TEMPLATES_REQUIRE_SOURCE +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +#define ACE_LACKS_UNIX_DOMAIN_SOCKETS +#define ACE_LACKS_SYSCALL +#define ACE_LACKS_STRRECVFD +#define ACE_LACKS_MMAP +#define ACE_LACKS_SOCKETPAIR +#define ACE_HAS_SEMUN +#define ACE_LACKS_MSYNC +#define ACE_LACKS_MADVISE +#define ACE_NEEDS_WRITEV +#define ACE_NEEDS_READV +#define ACE_NEEDS_FTRUNCATE +#define ACE_LACKS_RLIMIT +#define ACE_LACKS_RECVMSG +#define ACE_LACKS_SENDMSG + +// Compiler doesn't support static data member templates. +//#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +//#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +//#define ACE_HAS_SYSCALL_H + +// Fixes a problem with HP/UX not wrapping the mmap(2) header files +// with extern "C". +//#define ACE_HAS_BROKEN_MMAP_H + +// Prototypes for both signal() and struct sigaction are consistent. +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Header files lack t_errno for ACE_TLI. +//#define ACE_LACKS_T_ERRNO + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform defines the sig_atomic_t typedef +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler supports the ssize_t typedef. +//#define ACE_HAS_SSIZE_T + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// ??? +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// HP/UX has an undefined syscall for GETRUSAGE... +//#define ACE_HAS_SYSCALL_GETRUSAGE + +// Note, this only works if the flag is set above! +//#define ACE_HAS_GETRUSAGE + +// Platform uses int for select() rather than fd_set. +#define ACE_SELECT_USES_INT + +// Platform has prototypes for ACE_TLI. +//#define ACE_HAS_TLI_PROTOTYPES +// Platform has the XLI version of ACE_TLI. +// #define ACE_HAS_XLI + +#define ACE_HAS_GNU_CSTRING_H + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos4-g++.h b/ace/config-sunos4-g++.h new file mode 100644 index 00000000000..e20835a7b3d --- /dev/null +++ b/ace/config-sunos4-g++.h @@ -0,0 +1,94 @@ +/* -*- C++ -*- */ +// $Id$ + +// for SunOS4 platforms using the GNU g++ compiler + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_NEEDS_SYSTIME_H + +// Must specialize templates due to G++'s lame parameterized type +// support... +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform supports strerror (). +// #define ACE_HAS_STRERROR +#define ACE_HAS_SYS_ERRLIST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Header files lack t_errno for ACE_TLI. +// #define ACE_LACKS_T_ERRNO + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Compiler/platform uses old malloc()/free() prototypes (ugh). +#define ACE_HAS_OLD_MALLOC + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler has system V signals +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H +// Platform supports ACE_TLI tiuser header. +// #define ACE_HAS_TIUSER_H + +// Platform has ACE_TLI. +// #define ACE_HAS_TLI + +#define ACE_HAS_SUNOS4_SIGNAL_T +#define ACE_HAS_CPLUSPLUS_HEADERS +#define ACE_HAS_RTLD_LAZY_V +#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)) +#define ACE_HAS_SYSENT_H +#endif +#define ACE_HAS_ALLOCA +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H +#define ACE_HAS_SVR4_GETTIMEOFDAY +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos4-lucid3.2.h b/ace/config-sunos4-lucid3.2.h new file mode 100644 index 00000000000..92438ea3c7d --- /dev/null +++ b/ace/config-sunos4-lucid3.2.h @@ -0,0 +1,83 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for SunOS4 platforms using the Lucid 3.2 compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_SYS_ERRLIST + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Header files lack t_errno for ACE_TLI. +// #define ACE_LACKS_T_ERRNO + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Compiler/platform supports strerror (). +// #define ACE_HAS_STRERROR + +// SunOS 4 style prototype. +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform provides <sysent.h> header. +#define ACE_HAS_SYSENT_H + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Platform supports ACE_TLI tiuser header. +// #define ACE_HAS_TIUSER_H + +// Platform has ACE_TLI. +// #define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos4-sun3.x.h b/ace/config-sunos4-sun3.x.h new file mode 100644 index 00000000000..62e63a6098e --- /dev/null +++ b/ace/config-sunos4-sun3.x.h @@ -0,0 +1,71 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for SunOS4 platforms using the SunC++ 3.0.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_SYS_ERRLIST + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Header files lack t_errno for ACE_TLI. +// #define ACE_LACKS_T_ERRNO + +// Compiler/platform uses old malloc()/free() prototypes (ugh). +#define ACE_HAS_OLD_MALLOC + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// SunOS 4 style prototype. +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Platform supports ACE_TLI tiuser header. +// #define ACE_HAS_TIUSER_H + +// Platform has ACE_TLI. +// #define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos4-sun4.1.4.h b/ace/config-sunos4-sun4.1.4.h new file mode 100644 index 00000000000..8e97561bf41 --- /dev/null +++ b/ace/config-sunos4-sun4.1.4.h @@ -0,0 +1,82 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS4.1.4 +// platforms using the SunC++ 4.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_NEEDS_SYSTIME_H + +// Special addition to handle sunOS 4.1 which is unable to +// handle POSIX Prototypes ! +#define ACE_LACKS_POSIX_PROTO + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform supports strerror (). +// #define ACE_HAS_STRERROR +#define ACE_HAS_SYS_ERRLIST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Header files lack t_errno for ACE_TLI. +// #define ACE_LACKS_T_ERRNO + +// Compiler/platform uses old malloc()/free() prototypes (ugh). +#define ACE_HAS_OLD_MALLOC + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler has brain-damaged SPARCwork signal prototype... +#define ACE_HAS_SPARCWORKS_401_SIGNALS + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// SunOS 4 style prototype. +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Platform supports ACE_TLI tiuser header. +// #define ACE_HAS_TIUSER_H + +// Platform has ACE_TLI. +// #define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos4-sun4.x-orbix.h b/ace/config-sunos4-sun4.x-orbix.h new file mode 100644 index 00000000000..d3e593eef88 --- /dev/null +++ b/ace/config-sunos4-sun4.x-orbix.h @@ -0,0 +1,82 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for SunOS4 platforms using the SunC++ 4.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// ACE sparcworks 4.01 signal handling under SunOS +#define ACE_HAS_SPARCWORKS_401_SIGNALS + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Platform contains Orbix CORBA implementation. +#define ACE_HAS_ORBIX + +// Compiler/platform supports strerror (). +// #define ACE_HAS_STRERROR +#define ACE_HAS_SYS_ERRLIST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Header files lack t_errno for ACE_TLI. +// #define ACE_LACKS_T_ERRNO + +// Compiler/platform uses old malloc()/free() prototypes (ugh). +#define ACE_HAS_OLD_MALLOC + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler has brain-damaged SPARCwork signal prototype... +#define ACE_HAS_SPARCWORKS_401_SIGNALS + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// SunOS 4 style prototype. +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Platform supports ACE_TLI tiuser header. +// #define ACE_HAS_TIUSER_H + +// Platform has ACE_TLI. +// #define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos4-sun4.x.h b/ace/config-sunos4-sun4.x.h new file mode 100644 index 00000000000..9d1a71aa56b --- /dev/null +++ b/ace/config-sunos4-sun4.x.h @@ -0,0 +1,76 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for SunOS4 platforms using the SunC++ 4.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform supports strerror (). +// #define ACE_HAS_STRERROR +#define ACE_HAS_SYS_ERRLIST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Header files lack t_errno for ACE_TLI. +// #define ACE_LACKS_T_ERRNO + +// Compiler/platform uses old malloc()/free() prototypes (ugh). +#define ACE_HAS_OLD_MALLOC + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Compiler/platform supports poll(). +#define ACE_HAS_POLL + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler has brain-damaged SPARCwork signal prototype... +#define ACE_HAS_SPARCWORKS_401_SIGNALS + +// Compiler/platform supports struct strbuf +#define ACE_HAS_STRBUF_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// SunOS 4 style prototype. +#define ACE_HAS_SUNOS4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Platform supports ACE_TLI tiuser header. +// #define ACE_HAS_TIUSER_H + +// Platform has ACE_TLI. +// #define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.4-centerline-2.x.h b/ace/config-sunos5.4-centerline-2.x.h new file mode 100644 index 00000000000..9c7aa2debb3 --- /dev/null +++ b/ace/config-sunos5.4-centerline-2.x.h @@ -0,0 +1,152 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.4 +// platforms using the Centerline 2.x C++ compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_UNICODE + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Sun has the wrong prototype for sendmsg. +#define ACE_HAS_BROKEN_SENDMSG + +// The SunOS 5.x version of rand_r is inconsistent with the header files... +#define ACE_HAS_BROKEN_RANDR + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Platform has terminal ioctl flags like TCGETS and TCSETS. +#define ACE_HAS_TERM_IOCTLS + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Andreas Ueltschi tells me this is a good thing... +#define ACE_HAS_SVR5_GETTIMEOFDAY + +// Compiler/platform supports poll(). +#define ACE_HAS_SVR4_POLL + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform supports Solaris threads. +#define ACE_HAS_STHREADS + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.4-g++.h b/ace/config-sunos5.4-g++.h new file mode 100644 index 00000000000..0add5d1b80d --- /dev/null +++ b/ace/config-sunos5.4-g++.h @@ -0,0 +1,180 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.4 +// platforms using the GNU g++ compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_UNICODE + +// Must specialize templates due to G++'s lame parameterized type +// support... +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Sun has the wrong prototype for sendmsg. +#define ACE_HAS_BROKEN_SENDMSG + +// The SunOS 5.x version of rand_r is inconsistent with the header files... +// #define ACE_HAS_BROKEN_RANDR + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE + +// Denotes that GNU has cstring.h as standard +// which redefines memchr() +#define ACE_HAS_GNU_CSTRING_H + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler has system V signals +// #define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports Solaris threads. +#define ACE_HAS_STHREADS + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Define this file to keep /usr/include/memory.h from being included. +#include <cstring> + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.4-sunc++-4.x-orbix.h b/ace/config-sunos5.4-sunc++-4.x-orbix.h new file mode 100644 index 00000000000..83a3cdcbe82 --- /dev/null +++ b/ace/config-sunos5.4-sunc++-4.x-orbix.h @@ -0,0 +1,168 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.4 +// platforms using the SunC++ 4.0.x compiler. This works with the +// MT-Orbix CORBA IDL compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_UNICODE + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Sun has the wrong prototype for sendmsg. +#define ACE_HAS_BROKEN_SENDMSG + +// The SunOS 5.x version of rand_r is inconsistent with the header files... +#define ACE_HAS_BROKEN_RANDR + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Platform has terminal ioctl flags like TCGETS and TCSETS. +#define ACE_HAS_TERM_IOCTLS + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains the Orbix CORBA implementation. +#define ACE_HAS_ORBIX + +// Platform contains the multi-threaded Orbix CORBA implementation. +// #define ACE_HAS_MT_ORBIX + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports Solaris threads. +#define ACE_HAS_STHREADS + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.4-sunc++-4.x.h b/ace/config-sunos5.4-sunc++-4.x.h new file mode 100644 index 00000000000..5d25574ccb0 --- /dev/null +++ b/ace/config-sunos5.4-sunc++-4.x.h @@ -0,0 +1,165 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.4 +// platforms using the SunC++ 4.0.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_UNICODE + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Sun has the wrong prototype for sendmsg. +#define ACE_HAS_BROKEN_SENDMSG + +// The SunOS 5.x version of rand_r is inconsistent with the header files... +#define ACE_HAS_BROKEN_RANDR + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library. +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Platform has terminal ioctl flags like TCGETS and TCSETS. +#define ACE_HAS_TERM_IOCTLS + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports Solaris threads. +#define ACE_HAS_STHREADS + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Reactor detects deadlock +// #define ACE_REACTOR_HAS_DEADLOCK_DETECTION + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +// #define ACE_NTRACE 0 +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.5-g++.h b/ace/config-sunos5.5-g++.h new file mode 100644 index 00000000000..8917421aebf --- /dev/null +++ b/ace/config-sunos5.5-g++.h @@ -0,0 +1,171 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.5 +// platforms using the GNU g++ compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_UNICODE + +// Must specialize templates due to G++'s lame parameterized type +// support... +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE + +// Denotes that GNU has cstring.h as standard +// which redefines memchr() +#define ACE_HAS_GNU_CSTRING_H + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform supports POSIX pthreads *and* Solaris threads! +#define ACE_HAS_STHREADS +#define ACE_HAS_PTHREADS +#define ACE_HAS_SIGWAIT +#define ACE_LACKS_CONDATTR_PSHARED + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// Define this file to keep /usr/include/memory.h from being included. +#include <cstring> + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.5-sunc++-4.x-orbix.h b/ace/config-sunos5.5-sunc++-4.x-orbix.h new file mode 100644 index 00000000000..3c325dab04e --- /dev/null +++ b/ace/config-sunos5.5-sunc++-4.x-orbix.h @@ -0,0 +1,166 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.5 +// platforms using the SunC++ 4.0.x compiler. This works with the +// Orbix 2.0 CORBA IDL compiler. + + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Platform contains the Orbix CORBA implementation. +#define ACE_HAS_ORBIX + +// Platform contains the multi-threaded Orbix CORBA implementation. +//#define ACE_HAS_MT_ORBIX + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library. +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Platform has terminal ioctl flags like TCGETS and TCSETS. +#define ACE_HAS_TERM_IOCTLS + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform supports POSIX pthreads *and* Solaris threads! +#define ACE_HAS_STHREADS +#define ACE_HAS_PTHREADS +#define ACE_HAS_SIGWAIT +#define ACE_LACKS_CONDATTR_PSHARED + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Reactor detects deadlock +// #define ACE_REACTOR_HAS_DEADLOCK_DETECTION + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunos5.5-sunc++-4.x.h b/ace/config-sunos5.5-sunc++-4.x.h new file mode 100644 index 00000000000..63b4aaea320 --- /dev/null +++ b/ace/config-sunos5.5-sunc++-4.x.h @@ -0,0 +1,161 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS 5.5 +// platforms using the SunC++ 4.0.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_UNICODE + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Platform supports system configuration information. +#define ACE_HAS_SYSINFO + +// Platform supports the POSIX regular expression library. +#define ACE_HAS_REGEX + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Platform supports reentrant functions (i.e., all the POSIX *_r functions). +#define ACE_HAS_REENTRANT_FUNCTIONS + +// Platform has terminal ioctl flags like TCGETS and TCSETS. +#define ACE_HAS_TERM_IOCTLS + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Comment out the following seven defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform supports POSIX pthreads *and* Solaris threads! +#define ACE_HAS_STHREADS +#define ACE_HAS_PTHREADS +#define ACE_HAS_SIGWAIT +#define ACE_LACKS_CONDATTR_PSHARED + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE +/* End of threading #defines */ + +// Reactor detects deadlock +// #define ACE_REACTOR_HAS_DEADLOCK_DETECTION + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-sunx86-sunc++-4.x.h b/ace/config-sunx86-sunc++-4.x.h new file mode 100644 index 00000000000..c29373b495b --- /dev/null +++ b/ace/config-sunx86-sunc++-4.x.h @@ -0,0 +1,142 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for SunOS5.x86 +// platforms using the SunC++ 4.0.x compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Platform supports recvmsg and sendmsg. +#define ACE_HAS_MSG + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +// Compiler/platform correctly calls init()/fini() for shared libraries. +#define ACE_HAS_AUTOMATIC_INIT_FINI + +// Platform supports POSIX O_NONBLOCK semantics. +#define ACE_HAS_POSIX_NONBLOCK + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Compiler/platform supports SunOS high resolution timers. +#define ACE_HAS_HI_RES_TIMER + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Compiler/platform supports the "long long" datatype. +#define ACE_HAS_LONGLONG_T + +// Compiler/platform supports alloca() +#define ACE_HAS_ALLOCA + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +#define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SVR4_TIME + +// Platform supports the /proc file system. +#define ACE_HAS_PROC_FS + +// Platform supports the prusage_t struct. +#define ACE_HAS_PRUSAGE_T + +// Explicit dynamic linking permits "lazy" symbol resolution. +#define ACE_HAS_RTLD_LAZY_V + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Platform supports SVR4 extended signals. +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T + +// Compiler/platform provides the sockio.h file. +#define ACE_HAS_SOCKIO_H + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Platform supports STREAMS. +#define ACE_HAS_STREAMS + +// Platform supports STREAM pipes. +#define ACE_HAS_STREAM_PIPES + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Compiler/platform supports struct strbuf. +#define ACE_HAS_STRBUF_T + +// Compiler/platform supports SVR4 dynamic linking semantics. +#define ACE_HAS_SVR4_DYNAMIC_LINKING + +// Compiler/platform supports SVR4 gettimeofday() prototype. +#define ACE_HAS_SVR4_GETTIMEOFDAY + +// Compiler/platform supports SVR4 signal typedef. +#define ACE_HAS_SVR4_SIGNAL_T +//#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Compiler/platform supports SVR4 ACE_TLI (in particular, T_GETNAME stuff)... +#define ACE_HAS_SVR4_TLI + +// Platform provides <sys/filio.h> header. +#define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports Solaris threads. +#define ACE_HAS_STHREADS + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform has ACE_TLI. +#define ACE_HAS_TLI + +// Platform supports ACE_TLI timod STREAMS module. +#define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +#define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +#define ACE_HAS_TLI_PROTOTYPES + +// Platform supports ACE_TLI. +#define ACE_HAS_TLI + +// Use the poll() event demultiplexor rather than select(). +//#define ACE_USE_POLL + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-unixware-2.01-g++.h b/ace/config-unixware-2.01-g++.h new file mode 100644 index 00000000000..8e48ada35e2 --- /dev/null +++ b/ace/config-unixware-2.01-g++.h @@ -0,0 +1,95 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work +// for Unixware platforms running UnixWare 2.01. +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// See README for what the ACE_HAS... and ACE_LACKS... macros mean + +#define ACE_HAS_SIZET_SOCKET_LEN +#define ACE_HAS_AUTOMATIC_INIT_FINI +#define ACE_HAS_CPLUSPLUS_HEADERS +#define ACE_HAS_GNU_CSTRING_H +#define ACE_HAS_INLINED_OSCALLS +#define ACE_HAS_MSG +// Not yet sure about threads +#define ACE_HAS_MT_SAFE_SOCKETS +#define ACE_HAS_NONCONST_GETBY +#define ACE_HAS_OSF1_GETTIMEOFDAY +#define ACE_HAS_POLL +#define ACE_HAS_POSIX_NONBLOCK +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_REENTRANT_FUNCTIONS +#define ACE_HAS_REGEX +#define ACE_HAS_LAZY_V +#define ACE_HAS_SELECT_H +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_UCONTEXT_T +#define ACE_HAS_SIGWAIT +#define ACE_HAS_SIG_ATOMIC_T +#define ACE_HAS_SOCKIO_H +#define ACE_HAS_SSIZE_T +#define ACE_HAS_STHREADS +#define ACE_HAS_STRBUF_T +#define ACE_HAS_STREAMS +#define ACE_HAS_STREAM_PIPES +#define ACE_HAS_STRERROR +#define ACE_HAS_SVR4_DYNAMIC_LINKING +#define ACE_HAS_SVR4_TIME +#define ACE_HAS_SYSCALL_H +#define ACE_HAS_SYSINFO +#define ACE_HAS_SYSV_IPC +#define ACE_HAS_SYS_FILIO_H +#define ACE_HAS_SYS_SIGLIST +#define ACE_HAS_TERM_IOCTLS +#define ACE_HAS_THREADS +#define ACE_HAS_THREAD_SPECIFIC_STORAGE +#define ACE_HAS_THREAD_T +#define ACE_HAS_TIMOD_H +#define ACE_HAS_TIUSER_H +#define ACE_HAS_TLI +#define ACE_HAS_TLI_PROTOTYPES +#define ACE_HAS_UNIXWARE_SVR4_SIGNAL_T +#define ACE_HAS_VOIDPTR_SOCKOPT + +#define ACE_LACKS_MADVISE +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES +#define ACE_LACKS_SYSCALL + +#define ACE_MT_SAFE +#define ACE_PAGE_SIZE 4096 +#define ACE_REDEFINES_XTI_FUNCTIONS +#define ACE_TEMPLATES_REQUIRE_SOURCE +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + + +// Compiling for UNIXWARE +#if !defined (UNIXWARE) +#define UNIXWARE +#endif /* UNIXWARE */ + +// These seem to be missing... Process_Manager uses them +// +//typedef int Process_t; +//typedef int hProcess_t; +//typedef int hpid_t; + + +// Compiler/platform supports OSF/1 gettimeofday() prototype. +//#define ACE_HAS_OSF1_GETTIMEOFDAY + +// Compiler/platform supports SVR4 TLI (in particular, T_GETNAME stuff)... +//#define ACE_HAS_SVR4_TLI + + +// Platform doesn't have get<blah>by... char *arg defined as const +//#define ACE_GET_BLAH_BY_NO_CONST + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-vxworks-ghs-1.8.h b/ace/config-vxworks-ghs-1.8.h new file mode 100644 index 00000000000..deee0c0209e --- /dev/null +++ b/ace/config-vxworks-ghs-1.8.h @@ -0,0 +1,46 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for VxWorks +// 5.2 platforms using the GreenHills 1.8.7 compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +#define ACE_HAS_BROKEN_SENDMSG +#define ACE_HAS_BROKEN_WRITEV +#define ACE_HAS_CHARPTR_SOCKOPT +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES +#define ACE_HAS_CPLUSPLUS_HEADERS +#define ACE_HAS_GREENHILLS_SOCKETS +#define ACE_HAS_MSG +#define ACE_HAS_MT_SAFE_SOCKETS +#define ACE_HAS_POSIX_NONBLOCK +#define ACE_HAS_POSIX_TIME +#define ACE_HAS_SIG_ATOMIC_T +#define ACE_HAS_SIGINFO_T +#define ACE_HAS_SIGWAIT +#define ACE_HAS_THREADS +#define ACE_LACKS_MADVISE +#define ACE_LACKS_MALLOC_H +#define ACE_LACKS_MKTEMP +#define ACE_LACKS_MMAP +#define ACE_LACKS_MSYNC +#define ACE_LACKS_PARAM_H +#define ACE_LACKS_RLIMIT +#define ACE_LACKS_SBRK +#define ACE_LACKS_SEMBUF_T +#define ACE_LACKS_SIGINFO_H +#define ACE_LACKS_SI_ADDR +#define ACE_LACKS_SOCKETPAIR +#define ACE_LACKS_STRRECVFD +#define ACE_LACKS_SYSCALL +#define ACE_LACKS_UCONTEXT_H +#define ACE_LACKS_UTSNAME_T +#define ACE_MT_SAFE +#define SIGNAL_SAFE_OS_CALLS + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-win32-msvc2.0.h b/ace/config-win32-msvc2.0.h new file mode 100644 index 00000000000..a438b6ffe41 --- /dev/null +++ b/ace/config-win32-msvc2.0.h @@ -0,0 +1,133 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for Windows NT +// platforms using the Microsoft Visual C++ 2.0 compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Needed for timeval. +#include <winsock.h> + +#define ACE_HAS_UNICODE + +// Compiler/platform correctly calls init()/fini() for shared +// libraries. - applied for DLLs ? +//define ACE_HAS_AUTOMATIC_INIT_FINI + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// #define ACE_HAS_ORBIX + +// Version 1.1 of WinSock +#define ACE_WSOCK_VERSION 1, 1 +#define ACE_LACKS_RECVMSG +#define ACE_LACKS_SENDMSG +#define ACE_LACKS_MODE_MASKS + +#define ACE_LACKS_SBRK +#define ACE_LACKS_UTSNAME_T +#define ACE_LACKS_SEMBUF_T +#define ACE_LACKS_MSGBUF_T +#define ACE_LACKS_SYSV_SHMEM + +// Platform supports POSIX O_NONBLOCK semantics. +//define ACE_HAS_POSIX_NONBLOCK + +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +#define ACE_LACKS_STRRECVFD + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +//define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +//define ACE_HAS_POSIX_TIME + +// This needs to be here since MSVC++ 2.0 seems to have forgotten to +// include it. +inline void *operator new (unsigned int, void *p) { return p; } + +// Platform supports the /proc file system. +//define ACE_HAS_PROC_FS + +// Platform supports the rusage struct. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Andreas Ueltschi tells me this is a good thing... +#define ACE_HAS_SVR5_GETTIMEOFDAY + +// Compiler/platform supports poll(). +//define ACE_HAS_SVR4_POLL + +// Compiler/platform supports SVR4 signal typedef. +//define ACE_HAS_SVR4_SIGNAL_T + +// Platform provides <sys/filio.h> header. +//define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +//define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform supports Windows32 threads. +#define ACE_HAS_WTHREADS +#define ACE_WIN32 +#define ACE_HAS_TEMPLATE_INSTANTIATION + +//#define ACE_HAS_ALLOC_HOOKS +#define ACE_TEMPLATES_REQUIRE_SOURCE + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports ACE_TLI timod STREAMS module. +//define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +//define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +// For Win32, this is not really true, but saves a lot of hassle! +#define ACE_HAS_TLI_PROTOTYPES +#define ACE_HAS_GNU_CSTRING_H +// Platform supports ACE_TLI. +//define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ +// #define ACE_NLOGGING + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// I'm pretty sure NT lacks these +#define ACE_LACKS_UNIX_DOMAIN_SOCKETS + +// Windows NT needs readv() and writev() +#define ACE_NEEDS_WRITEV +#define ACE_NEEDS_READV + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-win32-msvc4.0.h b/ace/config-win32-msvc4.0.h new file mode 100644 index 00000000000..aacf85f8d73 --- /dev/null +++ b/ace/config-win32-msvc4.0.h @@ -0,0 +1,167 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for Windows NT +// platforms using the Microsoft Visual C++ 4.0 compiler. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Needed for timeval. +#include <winsock.h> + +#if defined (_MSC_VER) +// "C4355: 'this' : used in base member initializer list" +#pragma warning(disable:4355) // disable C4514 warning +// #pragma warning(default:4355) // use this to reenable, if desired +#endif /* _MSC_VER */ +// While digging the MSVC 4.0 include files, I found how to disable MSVC +// warnings: +// --Amos Shapira + +// <windows.h> and MFC's <afxwin.h> are mutually +// incompatible. <windows.h> is brain-dead about MFC; it doesn't check +// to see whether MFC stuff is anticipated or already in progress +// before doing its thing. ACE needs (practically always) <winsock.h>, +// and winsock in turn needs support either from windows.h or from +// afxwin.h. One or the other, not both. +// +// The MSVC++ V4.0 environment defines preprocessor macros that +// indicate the programmer has chosen something from the +// Build-->Settings-->General-->MFC combo-box. <afxwin.h> defines a +// macro itself to protect against double inclusion. We'll take +// advantage of all this to select the proper support for winsock. - +// trl 26-July-1996 + +#ifdef _AFXDLL // May be defined by MSVC++ IDE +#include <afxwin.h> // He is doing MFC +#endif +#ifdef _WINDLL // May be defined by MSVC++ IDE +#include <afxwin.h> // He is doing MFC +#endif + +#ifndef __AFX_H__ // set in afxwin.h +#include <windows.h> // if he's not doing MFC, snag this +#endif + +#define ACE_HAS_UNICODE + +// Uncomment these if you want to integrate ACE and Orbix in Win32. +// #define ACE_HAS_ORBIX +// #define ACE_HAS_MT_ORBIX + +#define ACE_LACKS_SBRK +#define ACE_LACKS_UTSNAME_T +#define ACE_LACKS_SEMBUF_T +#define ACE_LACKS_MSGBUF_T +#define ACE_LACKS_SYSV_SHMEM + +// Build as as a DLL. Zap this line if you want to build a static +// lib. +#define ACE_HAS_DLL + +// Compiler/platform correctly calls init()/fini() for shared +// libraries. - applied for DLLs ? +//define ACE_HAS_AUTOMATIC_INIT_FINI + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Version 1.1 of WinSock +#define ACE_WSOCK_VERSION 1, 1 +#define ACE_LACKS_RECVMSG +#define ACE_LACKS_SENDMSG + +// Platform supports POSIX O_NONBLOCK semantics. +//define ACE_HAS_POSIX_NONBLOCK + +#define ACE_LACKS_MODE_MASKS +#define ACE_LACKS_STRRECVFD + +// Compiler/platform has correctly prototyped header files. +#define ACE_HAS_CPLUSPLUS_HEADERS + +// Platform supports IP multicast +#define ACE_HAS_IP_MULTICAST + +// Sockets may be called in multi-threaded programs. +#define ACE_HAS_MT_SAFE_SOCKETS + +// Platform contains <poll.h>. +//define ACE_HAS_POLL + +// Platform supports POSIX timers via timestruc_t. +//define ACE_HAS_POSIX_TIME + +// Platform supports the /proc file system. +//define ACE_HAS_PROC_FS + +// Platform supports the rusage struct. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Andreas Ueltschi tells me this is a good thing... +#define ACE_HAS_SVR5_GETTIMEOFDAY + +// Compiler/platform supports poll(). +//define ACE_HAS_SVR4_POLL + +// Compiler/platform supports SVR4 signal typedef. +//define ACE_HAS_SVR4_SIGNAL_T + +// Platform provides <sys/filio.h> header. +//define ACE_HAS_SYS_FILIO_H + +// Compiler/platform supports sys_siglist array. +//define ACE_HAS_SYS_SIGLIST + +/* Turn off the following four defines if you want to disable threading. */ +// Compile using multi-thread libraries. +#define ACE_MT_SAFE + +// Platform supports threads. +#define ACE_HAS_THREADS + +// Platform supports Windows32 threads. +#define ACE_HAS_WTHREADS +#define ACE_WIN32 +#define ACE_HAS_TEMPLATE_INSTANTIATION + +//#define ACE_HAS_ALLOC_HOOKS +#define ACE_TEMPLATES_REQUIRE_SOURCE + +// Compiler/platform has thread-specific storage +#define ACE_HAS_THREAD_SPECIFIC_STORAGE + +// Platform supports ACE_TLI timod STREAMS module. +//define ACE_HAS_TIMOD_H + +// Platform supports ACE_TLI tiuser header. +//define ACE_HAS_TIUSER_H + +// Platform provides ACE_TLI function prototypes. +// For Win32, this is not really true, but saves a lot of hassle! +#define ACE_HAS_TLI_PROTOTYPES +#define ACE_HAS_GNU_CSTRING_H +// Platform supports ACE_TLI. +//define ACE_HAS_TLI + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ +// #define ACE_NLOGGING + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +// I'm pretty sure NT lacks these +#define ACE_LACKS_UNIX_DOMAIN_SOCKETS + +// Windows NT needs readv() and writev() +#define ACE_NEEDS_WRITEV +#define ACE_NEEDS_READV + +#endif /* ACE_CONFIG_H */ diff --git a/ace/makefile-light b/ace/makefile-light new file mode 100644 index 00000000000..af44520c851 --- /dev/null +++ b/ace/makefile-light @@ -0,0 +1,883 @@ +#---------------------------------------------------------------------------- +# @(#)makefile-light 1.1 10/18/96 +# +# Sun Makefile for a lightweight version of the ACE library +# +# 1. The Reactor class category +# 2. The SOCK_SAP C++ wrappers for sockets +# 3. The threading and synchronization wrappers. +# 4. The Acceptor/Connector classes +#---------------------------------------------------------------------------- + +LIB = libIR_ACE.a +SHLIB = libIR_ACE.so + +SRC = Acceptor.C \ + Addr.C \ + Atomic_Op.C \ + Connector.C \ + Event_Handler.C \ + Event_Handler_T.C \ + Get_Opt.C \ + Handle_Set.C \ + INET_Addr.C \ + IPC_SAP.C \ + LSOCK.C \ + LSOCK_Acceptor.C \ + LSOCK_CODgram.C \ + LSOCK_Connector.C \ + LSOCK_Dgram.C \ + LSOCK_Stream.C \ + Misc.C \ + Reactor.C \ + SOCK.C \ + SOCK_Acceptor.C \ + SOCK_CODgram.C \ + SOCK_Connector.C \ + SOCK_Dgram.C \ + SOCK_Dgram_Bcast.C \ + SOCK_IO.C \ + SOCK_Dgram_Mcast.C \ + SOCK_Stream.C \ + Signal.C \ + Svc_Handler.C \ + Synch.C \ + Thread.C \ + Thread_Manager.C \ + Time_Value.C \ + Timer_Queue.C \ + Token.C \ + UNIX_Addr.C + +OBJ = Acceptor.o \ + Addr.o \ + Atomic_Op.o \ + Connector.o \ + Event_Handler.o \ + Event_Handler_T.o \ + Get_Opt.o \ + Handle_Set.o \ + INET_Addr.o \ + IPC_SAP.o \ + LSOCK.o \ + LSOCK_Acceptor.o \ + LSOCK_CODgram.o \ + LSOCK_Connector.o \ + LSOCK_Dgram.o \ + LSOCK_Stream.o \ + Misc.o \ + Reactor.o \ + SOCK.o \ + SOCK_Acceptor.o \ + SOCK_CODgram.o \ + SOCK_Connector.o \ + SOCK_Dgram.o \ + SOCK_Dgram_Bcast.o \ + SOCK_IO.o \ + SOCK_Dgram_Mcast.o \ + SOCK_Stream.o \ + Signal.o \ + Svc_Handler.o \ + Synch.o \ + Thread.o \ + Thread_Manager.o \ + Time_Value.o \ + Timer_Queue.o \ + Token.o \ + UNIX_Addr.o + +SHOBJ = Acceptor.so \ + Addr.so \ + Atomic_Op.so \ + Connector.so \ + Event_Handler.so \ + Event_Handler_T.so \ + Get_Opt.so \ + Handle_Set.so \ + INET_Addr.so \ + IPC_SAP.so \ + LSOCK.so \ + LSOCK_Acceptor.so \ + LSOCK_CODgram.so \ + LSOCK_Connector.so \ + LSOCK_Dgram.so \ + LSOCK_Stream.so \ + Misc.so \ + Reactor.so \ + SOCK.so \ + SOCK_Acceptor.so \ + SOCK_CODgram.so \ + SOCK_Connector.so \ + SOCK_Dgram.so \ + SOCK_Dgram_Bcast.so \ + SOCK_IO.so \ + SOCK_Dgram_Mcast.so \ + SOCK_Stream.so \ + Signal.so \ + Svc_Handler.so \ + Synch.so \ + Thread.so \ + Thread_Manager.so \ + Time_Value.so \ + Timer_Queue.so \ + Token.so \ + UNIX_Addr.so + +#---------------------------------------------------------------------------- +# Local Macros and Targets +#---------------------------------------------------------------------------- + +# Set up the suffixes for C++ and IDL. +.SUFFIXES: .cc .C $(SUFFIXES) + +%.o: %.C + $(COMPILE.cc) -o $@ $< + +%.o: %.cc + $(COMPILE.cc) -o $@ $< + +%.so: %.C + $(SOBUILD) + +# Turn off logging to remove the dependency on the Log_Msg class. +AR = CC +ARFLAGS = -xar -o +DEFFLAGS += -DACE_NLOGGING +INCLDIRS += -I$(WRAPPER_ROOT)/include +CPPFLAGS += $(DEFFLAGS) $(INCLDIRS) +CCFLAGS += -g +CXX = CC +DLD = $(CXX) +PIC = -pic +SOFLAGS = -G $(CPPFLAGS) +SOBUILD = $(COMPILE.cc) $(PIC) -o $(VSHDIR)$*.o $<; \ + $(SOLINK.cc) -o $@ -h $@ $(LDFLAGS) $(VSHDIR)$*.o + +COMPILE.cc =$(CXX) $(CCFLAGS) $(CPPFLAGS) -c +LINK.cc =$(CXX) $(CCFLAGS) $(CPPFLAGS) +SOLINK.cc =$(DLD) $(SOFLAGS) + +all: build + +build: $(SHLIB) # Replace with $(LIB) if you only want to build static libs. + +$(LIB): $(OBJ) + $(AR) $(ARFLAGS) $@ $? + +$(SHLIB): $(SHOBJ) + $(SOLINK.cc) -o $@ $(LDFLAGS) *.o -lsocket -lnsl + + -$(RM) -rf *.o *.so *~ *.bak makefile-light.old core Templates.DB + + -$(RM) -f *.o *~ *.bak Makefile.old core + -$(RM) -rf ptrepository Templates.DB + +realclean: clean + -$(RM) -f $(LIB) $(SHLIB) + +#---------------------------------------------------------------------------- +# Dependency generation target +#---------------------------------------------------------------------------- + +depend: makefile-light + @$(RM) -f makefile-light.old + @cp makefile-light makefile-light.old + $(WRAPPER_ROOT)/bin/g++dep -f makefile-light $(CPPFLAGS) $(SRC) + @cat makefile-light | \ + sed -e "s;$(WRAPPER_ROOT);$$(WRAPPER_ROOT);g" \ + -e "/:$$/d" \ + > makefile-light.new + @mv makefile-light.new makefile-light + @if cmp -s makefile-light makefile-light.old ;\ + then echo "Makefile dependencies unchanged." ;\ + else \ + echo "Makefile dependencies updated." ;\ + fi ;\ + $(RM) -f makefile-light.old ; + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +Acceptor.o: Acceptor.C \ + $(WRAPPER_ROOT)/include/ace/Acceptor.h \ + $(WRAPPER_ROOT)/include/ace/Service_Config.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.i \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/include/ace/Signal.h \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/Token.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Service_Repository.h \ + $(WRAPPER_ROOT)/include/ace/Service_Record.h \ + $(WRAPPER_ROOT)/include/ace/Service_Object.h \ + $(WRAPPER_ROOT)/include/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/include/ace/Stream.h \ + $(WRAPPER_ROOT)/include/ace/Module.h \ + $(WRAPPER_ROOT)/include/ace/Task.h \ + $(WRAPPER_ROOT)/include/ace/Trace.h \ + $(WRAPPER_ROOT)/include/ace/Message_Queue.h \ + $(WRAPPER_ROOT)/include/ace/IO_Cntl_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/include/ace/Svc_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Svc_Handler.i \ + $(WRAPPER_ROOT)/include/ace/Acceptor.i \ + $(WRAPPER_ROOT)/include/ace/Get_Opt.h +Addr.o: Addr.C \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Addr.i +Atomic_Op.o: Atomic_Op.C +Connector.o: Connector.C \ + $(WRAPPER_ROOT)/include/ace/Connector.h \ + $(WRAPPER_ROOT)/include/ace/Service_Config.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.i \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/include/ace/Signal.h \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/Token.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Service_Repository.h \ + $(WRAPPER_ROOT)/include/ace/Service_Record.h \ + $(WRAPPER_ROOT)/include/ace/Service_Object.h \ + $(WRAPPER_ROOT)/include/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/include/ace/Stream.h \ + $(WRAPPER_ROOT)/include/ace/Module.h \ + $(WRAPPER_ROOT)/include/ace/Task.h \ + $(WRAPPER_ROOT)/include/ace/Trace.h \ + $(WRAPPER_ROOT)/include/ace/Message_Queue.h \ + $(WRAPPER_ROOT)/include/ace/IO_Cntl_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/include/ace/Map_Manager.h \ + $(WRAPPER_ROOT)/include/ace/Svc_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Svc_Handler.i \ + $(WRAPPER_ROOT)/include/ace/Connector.i +Event_Handler.o: Event_Handler.C \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.i +Event_Handler_T.o: Event_Handler_T.C \ + $(WRAPPER_ROOT)/include/ace/Event_Handler_T.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler_T.i +Get_Opt.o: Get_Opt.C \ + $(WRAPPER_ROOT)/include/ace/Get_Opt.h \ + $(WRAPPER_ROOT)/include/ace/Get_Opt.i \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h +Handle_Set.o: Handle_Set.C \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.i +INET_Addr.o: INET_Addr.C \ + $(WRAPPER_ROOT)/include/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/INET_Addr.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +IPC_SAP.o: IPC_SAP.C \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i +LSOCK.o: LSOCK.C \ + $(WRAPPER_ROOT)/include/ace/LSOCK.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK.i +LSOCK_Acceptor.o: LSOCK_Acceptor.C \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Acceptor.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Acceptor.i \ + $(WRAPPER_ROOT)/include/ace/UNIX_Addr.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Stream.i +LSOCK_CODgram.o: LSOCK_CODgram.C \ + $(WRAPPER_ROOT)/include/ace/LSOCK_CODgram.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_CODgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_CODgram.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_CODgram.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +LSOCK_Connector.o: LSOCK_Connector.C \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Connector.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Stream.i \ + $(WRAPPER_ROOT)/include/ace/UNIX_Addr.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Connector.i +LSOCK_Dgram.o: LSOCK_Dgram.C \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Dgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Dgram.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +LSOCK_Stream.o: LSOCK_Stream.C \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK.h \ + $(WRAPPER_ROOT)/include/ace/LSOCK.i \ + $(WRAPPER_ROOT)/include/ace/LSOCK_Stream.i +Misc.o: Misc.C \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h +Reactor.o: Reactor.C \ + $(WRAPPER_ROOT)/include/ace/Reactor.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.i \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/include/ace/Signal.h \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/Token.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +SOCK.o: SOCK.C \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +SOCK_Acceptor.o: SOCK_Acceptor.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_Acceptor.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Acceptor.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +SOCK_CODgram.o: SOCK_CODgram.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_CODgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_CODgram.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +SOCK_Connector.o: SOCK_Connector.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_Connector.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.i \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Connector.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.i \ + $(WRAPPER_ROOT)/include/ace/INET_Addr.h +SOCK_Dgram.o: SOCK_Dgram.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +SOCK_Dgram_Bcast.o: SOCK_Dgram_Bcast.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram_Bcast.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram_Bcast.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +SOCK_IO.o: SOCK_IO.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i +SOCK_Dgram_Mcast.o: SOCK_Dgram_Mcast.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram_Mcast.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram.i \ + $(WRAPPER_ROOT)/include/ace/INET_Addr.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_Dgram_Mcast.i +SOCK_Stream.o: SOCK_Stream.C \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.h \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.h \ + $(WRAPPER_ROOT)/include/ace/SOCK.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/SOCK.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_IO.i \ + $(WRAPPER_ROOT)/include/ace/SOCK_Stream.i +Signal.o: Signal.C \ + $(WRAPPER_ROOT)/include/ace/Signal.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Signal.i +Svc_Handler.o: Svc_Handler.C \ + $(WRAPPER_ROOT)/include/ace/Svc_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Task.h \ + $(WRAPPER_ROOT)/include/ace/Trace.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Service_Object.h \ + $(WRAPPER_ROOT)/include/ace/Shared_Object.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Message_Queue.h \ + $(WRAPPER_ROOT)/include/ace/IO_Cntl_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/Service_Config.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.h \ + $(WRAPPER_ROOT)/include/ace/Handle_Set.i \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.i \ + $(WRAPPER_ROOT)/include/ace/Signal.h \ + $(WRAPPER_ROOT)/include/ace/Token.h \ + $(WRAPPER_ROOT)/include/ace/Reactor.i \ + $(WRAPPER_ROOT)/include/ace/Service_Repository.h \ + $(WRAPPER_ROOT)/include/ace/Service_Record.h \ + $(WRAPPER_ROOT)/include/ace/Stream.h \ + $(WRAPPER_ROOT)/include/ace/Module.h \ + $(WRAPPER_ROOT)/include/ace/Svc_Handler.i +Synch.o: Synch.C \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Synch.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Thread.h +Thread.o: Thread.C \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Thread.i +Thread_Manager.o: Thread_Manager.C \ + $(WRAPPER_ROOT)/include/ace/Thread_Manager.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Manager.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.h \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.h \ + $(WRAPPER_ROOT)/include/ace/FIFO.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.h \ + $(WRAPPER_ROOT)/include/ace/IPC_SAP.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send.i \ + $(WRAPPER_ROOT)/include/ace/FIFO_Send_Msg.i \ + $(WRAPPER_ROOT)/include/ace/Log_Record.h \ + $(WRAPPER_ROOT)/include/ace/Log_Priority.h \ + $(WRAPPER_ROOT)/include/ace/Log_Record.i \ + $(WRAPPER_ROOT)/include/ace/Log_Msg.i +Thread_Specific.o: Thread_Specific.C \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/Thread_Specific.i +Time_Value.o: Time_Value.C \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.i +Timer_Queue.o: Timer_Queue.C \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.h \ + $(WRAPPER_ROOT)/include/ace/Event_Handler.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Timer_Queue.i +Token.o: Token.C \ + $(WRAPPER_ROOT)/include/ace/Thread.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/Token.h \ + $(WRAPPER_ROOT)/include/ace/Synch.h \ + $(WRAPPER_ROOT)/include/ace/Time_Value.h +UNIX_Addr.o: UNIX_Addr.C \ + $(WRAPPER_ROOT)/include/ace/UNIX_Addr.h \ + $(WRAPPER_ROOT)/include/ace/Addr.h \ + $(WRAPPER_ROOT)/include/ace/sysincludes.h \ + $(WRAPPER_ROOT)/include/ace/config.h \ + $(WRAPPER_ROOT)/include/ace/Misc.h \ + $(WRAPPER_ROOT)/include/ace/UNIX_Addr.i + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY |