int DgramHandler::handle_timeout (const ACE_Time_Value ¤t_time, const void *act) { ACE_UNUSED_ARG (current_time); ACE_UNUSED_ARG (act); int sendBuffer = 0; if (++timeoutsTriggered_ >= expectedTriggers_) reactor ()->cancel_timer (this, 1); ACE_SOCK_Dgram socket; if (-1 == socket.open (ACE_INET_Addr (static_cast< u_short > (0), static_cast< ACE_UINT32 > (INADDR_ANY)), ACE_PROTOCOL_FAMILY_INET, 0, 1)) ACE_ERROR ((LM_ERROR, ACE_TEXT (" (%P) %p\n"), ACE_TEXT ("Cannot open socket for sending Qt dgrams"))); ACE_INET_Addr peerAddr; peer_.get_local_addr (peerAddr); if (sizeof (sendBuffer) != socket.send (&sendBuffer, sizeof (sendBuffer), peerAddr)) ACE_ERROR ((LM_ERROR, ACE_TEXT (" (%P) %p\n"), ACE_TEXT ("Cannot send dgram"))); else ++dgramsSent_; socket.close (); return 0; }
// Listing 2 code/ch09 void echo_dgram (void) { ACE_INET_Addr my_addr (ACE_static_cast (u_short, 10102)); ACE_INET_Addr your_addr; ACE_SOCK_Dgram udp (my_addr); char buff[BUFSIZ]; size_t buflen = sizeof (buff); ssize_t recv_cnt = udp.recv (buff, buflen, your_addr); if (recv_cnt > 0) udp.send (buff, ACE_static_cast (size_t, buflen), your_addr); udp.close (); return; }
int DgramHandler::handle_close (ACE_HANDLE handle, ACE_Reactor_Mask close_mask) { if (peer_.get_handle () != handle ) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Unknown handle %d DgramHandler::handle_close " "with mask %x. My handle is %d\n"), handle, close_mask, peer_.get_handle ())); else peer_.close (); return 0; }
int send_unicast (const ACE_INET_Addr &to) { const char *message = "this is the message!\n"; ACE_INET_Addr my_addr (ACE_static_cast (u_short, 10101)); ACE_SOCK_Dgram udp (my_addr); ssize_t sent = udp.send (message, ACE_OS_String::strlen (message) + 1, to); udp.close (); if (sent == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("send")), -1); return 0; }
int run_main (int argc, ACE_TCHAR *argv[]) { parse_args (argc, argv); // Child process code. if (child_nr >= 0) { ACE_TCHAR lognm[MAXPATHLEN]; int mypid (ACE_OS::getpid ()); ACE_OS::sprintf(lognm, ACE_TEXT ("RW_Process_Mutex_Test-child-%d"), (int)mypid); ACE_START_TEST (lognm); if (child_nr == 0) writer (); else reader (child_nr); ACE_END_LOG; } else { ACE_START_TEST (ACE_TEXT ("RW_Process_Mutex_Test")); // Although it should be safe for each process to construct and // destruct the rw lock, this can disturb other process still // using the lock. This is not really correct, and should be // looked at, but it gets things moving. // Also see Process_Mutex_Test.cpp for similar issue. ACE_RW_Process_Mutex mutex (mutex_name.c_str ()); // Make sure the constructor succeeded if (ACE_LOG_MSG->op_status () != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Parent, mutex %s %p\n"), mutex_name.c_str (), ACE_TEXT ("ctor"))); } #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR) static const ACE_TCHAR* format = ACE_TEXT ("%ls -c %d -p %u -n %ls"); #else static const ACE_TCHAR* format = ACE_TEXT ("%s -c %d -p %u -n %s"); #endif /* !ACE_WIN32 && ACE_USES_WCHAR */ // The parent process reads time ranges sent from the children via // UDP. Grab an unused UDP port to tell the children to send to. ACE_INET_Addr me; ACE_SOCK_Dgram sock; if (sock.open (ACE_Addr::sap_any, PF_INET) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Socket %p\n"), ACE_TEXT ("open")), -1); sock.get_local_addr (me); ACE_TCHAR me_str[80]; me.addr_to_string (me_str, 80); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Receiving on %s\n"), me_str)); // Spawn 1 writer and 3 reader processes that will contend for the // lock. Child writer; Child readers[Nr_Processes - 1]; int i; for (i = 0; i < Nr_Processes; i++) { Child *child = (i == 0 ? &writer : &readers[i-1]); ACE_Process_Options options; options.command_line (format, argc > 0 ? argv[0] : ACE_TEXT ("RW_Process_Mutex_Test"), i, (unsigned int)me.get_port_number (), mutex_name.c_str ()); if (child->spawn (options) == -1) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("spawn of child %d %p\n"), i, ACE_TEXT ("failed")), -1); } else { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Child process %d has pid = %d.\n"), i, (int)(child->getpid ()))); } } // Keep reading time ranges reported from the children until all the // children have exited. Alternate between checking for a range and // checking for exits. int processes = Nr_Processes; Child *children[Nr_Processes]; for (i = 0; i < Nr_Processes; i++) children[i] = (i == 0 ? &writer : &readers[i-1]); Range_Report report; ACE_Time_Value poll (0); ACE_INET_Addr from; ssize_t bytes; while (processes > 0) { ACE_Time_Value limit (10); bytes = sock.recv (&report, sizeof (report), from, 0, &limit); if (bytes > 0) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Report from child %d; %b bytes\n"), report.child_, bytes)); if (report.child_ == 0) writer.add_range (report.range_); else { if (report.child_ >= 1 && report.child_ < Nr_Processes) readers[report.child_ - 1].add_range (report.range_); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("Report from out-of-range child #%d\n"), report.child_)); } } else { if (errno == ETIME) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("UDP time out; check child exits\n"))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("UDP recv"))); } for (i = 0; i < Nr_Processes; i++) { if (children[i] == 0) continue; ACE_exitcode child_status; // See if the child has exited. int wait_result = children[i]->wait (poll, &child_status); if (wait_result == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Wait for child %d, %p\n"), i, ACE_TEXT ("error"))); else if (wait_result != 0) { if (child_status == 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Child %d finished ok\n"), (int)(children[i]->getpid ()))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("Child %d finished with status %d\n"), (int)(children[i]->getpid ()), child_status)); children[i] = 0; --processes; } } } sock.close (); if (0 != mutex.remove ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("mutex remove"))); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Comparing time ranges...\n"))); // The writer should never overlap any readers bool writer_overlap = false; for (i = 0; i < Nr_Processes - 1; ++i) { if (writer.any_overlaps (readers[i])) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer overlaps reader %d\n"), i+1)); writer_overlap = true; } } if (!writer_overlap) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer does not overlap with readers; Ok\n"))); // And there should be some overlap between readers. bool reader_overlap = false; for (i = 0; i < Nr_Processes - 1; ++i) { // Just compare to those higher, else it compares the same ones, // only in reverse. for (int j = i + 1; j < Nr_Processes - 1; ++j) { if (readers[i].any_overlaps (readers[j])) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d overlaps reader %d; Ok\n"), i + 1, j + 1)); reader_overlap = true; } } } if (!reader_overlap) ACE_ERROR ((LM_ERROR, ACE_TEXT ("No readers overlapped!\n"))); ACE_END_TEST; } return 0; }
static void writer (void) { ACE_RW_Process_Mutex mutex (mutex_name.c_str ()); // Make sure the constructor succeeded if (ACE_LOG_MSG->op_status () != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer, mutex %s %p\n"), mutex_name.c_str (), ACE_TEXT ("ctor"))); return; } ACE_SOCK_Dgram sock; ACE_INET_Addr parent; parent.set (reporting_port, ACE_LOCALHOST, 1, AF_INET); ACE_TCHAR me_str[80]; parent.addr_to_string (me_str, 80); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Sending reports to %s\n"), me_str)); if (sock.open (ACE_Addr::sap_any, PF_INET) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("UDP open"))); Range_Report report; report.child_ = 0; // We're the writer ACE_Time_Value start (ACE_Time_Value::zero), stop (ACE_Time_Value::zero); // Grab the lock if (-1 == mutex.acquire_write ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer first %p\n"), ACE_TEXT ("acquire_write"))); else { start = ACE_OS::gettimeofday (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer acquired first time\n"))); } // Now sleep, making the readers wait for the lock. Then release the lock, // sleep, and reacquire the lock. ACE_OS::sleep (2); stop = ACE_OS::gettimeofday (); if (-1 == mutex.release ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer %p\n"), ACE_TEXT ("first release"))); else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer released first time\n"))); report.range_.set (start, stop); ssize_t bytes = sock.send (&report, sizeof (report), parent); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer sent %b byte report\n"), bytes)); ACE_OS::sleep (1); // Ensure we don't immediately grab the lock back start = stop = ACE_Time_Value::zero; if (-1 == mutex.acquire_write ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer second %p\n"), ACE_TEXT ("acquire_write"))); else { start = ACE_OS::gettimeofday (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer acquired second time\n"))); } ACE_OS::sleep (2); stop = ACE_OS::gettimeofday (); if (-1 == mutex.release ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer %p\n"), ACE_TEXT ("second release"))); else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer released second time\n"))); report.range_.set (start, stop); bytes = sock.send (&report, sizeof (report), parent); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer sent %b byte report\n"), bytes)); sock.close (); return; }
/* * The set of readers and the writer will operate in a staggered sequence * of acquiring and releasing the lock. The sequence is designed to exercise * waiting behavior of both readers and writer, as well as allowing multiple * readers in, without getting tripped up by any differences in ordering * on different platforms which may favor writers, or vice-versa. * In this timeline, time on seconds is on the left, time holding the lock * is solid, time waiting is dots, acquire/release point is a dash, and * time without the lock is blank. * * TIME WRITER READER1 READER2 READER3 * 0 | * | * 1 | . * | . * 2 - - - * | | * 3 | | - * | | | * 4 - | | * | | * 5 - | * | * 6 - - * | * 7 | . . . * | . . . * 8 - - - - * | | | * 9 | | | * * A file is used to test the sequencing. When the writer first gets the * lock, it will ensure the file is not present. At the end of its time * holding the lock the first time, it will write a "writer 1" string to * the file. When it gets the lock the second time, it will write a * different string to the file, and just before releasing the second time * write a "writer 2" string to the file. The readers all check to be sure * that the file is present and says "writer 1" at the start and end of * their periods of holding the reader lock and, similarly, check for * "writer 2" the second time they hold the lock. */ static void reader (int num) { // Let the writer get there first. ACE_OS::sleep (1); ACE_SOCK_Dgram sock; ACE_INET_Addr parent; parent.set (reporting_port, ACE_LOCALHOST, 1, AF_INET); ACE_TCHAR me_str[80]; parent.addr_to_string (me_str, 80); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Sending reports to %s\n"), me_str)); if (sock.open (ACE_Addr::sap_any, PF_INET) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("UDP open"))); Range_Report report; report.child_ = num; ACE_Time_Value start (ACE_Time_Value::zero), stop (ACE_Time_Value::zero); ACE_RW_Process_Mutex mutex (mutex_name.c_str ()); // Make sure the constructor succeeded if (ACE_LOG_MSG->op_status () != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reader %d, mutex %s %p\n"), num, mutex_name.c_str (), ACE_TEXT ("ctor"))); return; } ACE_OS::sleep (num); // Grab the lock if (-1 == mutex.acquire_read ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reader %d %p\n"), num, ACE_TEXT ("first acquire_read"))); else { start = ACE_OS::gettimeofday (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d acquired first time\n"), num)); } // Wait a bit, then release and report the range held. ACE_OS::sleep (num); // Release the lock then wait; in the interim, the writer should change // the file. stop = ACE_OS::gettimeofday (); if (-1 == mutex.release ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reader %d %p\n"), num, ACE_TEXT ("first release"))); else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d released first time\n"), num)); report.range_.set (start, stop); ssize_t bytes = sock.send (&report, sizeof (report), parent); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d sent %b byte report\n"), num, bytes)); ACE_OS::sleep (4 - num); start = stop = ACE_Time_Value::zero; if (-1 == mutex.acquire_read ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reader %d %p\n"), num, ACE_TEXT ("second acquire_read"))); else { start = ACE_OS::gettimeofday (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d acquired second time\n"), num)); } // Done; small delay, release, report, and return. ACE_OS::sleep (1); stop = ACE_OS::gettimeofday (); if (-1 == mutex.release ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reader %d %p\n"), num, ACE_TEXT ("second release"))); else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d released second time; done\n"), num)); report.range_.set (start, stop); bytes = sock.send (&report, sizeof (report), parent); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d sent %b byte report\n"), num, bytes)); sock.close (); return; }