// Listing 1 // Listing 2 code/ch05 int SetExample::runUnboundedSet () { ACE_TRACE (ACE_TEXT ("SetExample::runUnboundedSet")); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using an unbounded set.\n"))); ACE_Unbounded_Set<DataElement*> uset; for (int m = 0; m < 100; m++) { DataElement *elem; ACE_NEW_RETURN (elem, DataElement (m), -1); uset.insert (elem); } DataElement deBegin (0), deEnd (99); if (!uset.find (&deBegin) && !uset.find (&deEnd)) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Found the elements\n"))); } // Iterate and destroy the elements in the set. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Deleting the elements\n"))); ACE_Unbounded_Set_Iterator<DataElement*> iter (uset); for (iter = uset.begin (); iter != uset.end (); iter++) { DataElement* elem = (*iter); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), elem->getData ())); delete elem; } return 0; }
static void test_boundaries (void) { ACE_Handle_Set handle_set; ACE_Unbounded_Set<ACE_HANDLE> set; ACE_HANDLE handle; // First test an empty set. for (ACE_Handle_Set_Iterator i1 (handle_set); (handle = i1 ()) != ACE_INVALID_HANDLE; ) { ACE_ASSERT (0 == ACE_TEXT ("this shouldn't get called since ") ACE_TEXT ("the set is empty!\n")); } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_DEFAULT_SELECT_REACTOR_SIZE %d\n"), ACE_DEFAULT_SELECT_REACTOR_SIZE)); // Insert the vector of <ACE_HANDLE>s into the set. #if defined (ACE_WIN64) // The casts below are legit... # pragma warning(push) # pragma warning(disable : 4312) #endif /* ACE_WIN64 */ for (int i = 0; handle_vector[i] != ACE_INVALID_HANDLE; i++) { if (handle_vector[i] < (ACE_HANDLE) ACE_DEFAULT_SELECT_REACTOR_SIZE) { handle_set.set_bit (handle_vector[i]); set.insert (handle_vector[i]); } } #if defined (ACE_WIN64) # pragma warning(pop) #endif /* ACE_WIN64 */ int count = 0; for (ACE_Handle_Set_Iterator i2 (handle_set); (handle = i2 ()) != ACE_INVALID_HANDLE; ) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("obtained handle %d\n"), handle)); int done = set.remove (handle); ACE_ASSERT (done == 0); count++; } ACE_ASSERT (count == handle_set.num_set ()); }
static void test_boundaries (void) { ACE_Handle_Set handle_set; ACE_Unbounded_Set<ACE_HANDLE> set; ACE_HANDLE handle; // First test an empty set. for (ACE_Handle_Set_Iterator i1 (handle_set); (handle = i1 ()) != ACE_INVALID_HANDLE; ) { #if defined (ACE_PSOS_DIAB) // Workaround for some compiler confusion with strings in // assertions. const int SET_IS_EMPTY_SO_SHOULD_NOT_SEE_THIS = 1; ACE_ASSERT (0 == SET_IS_EMPTY_SO_SHOULD_NOT_SEE_THIS); #else /* ! defined (ACE_PSOS_DIAB) */ ACE_ASSERT (0 == ACE_TEXT ("this shouldn't get called since ") ACE_TEXT ("the set is empty!\n")); #endif /* defined (ACE_PSOS_DIAB) */ } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_DEFAULT_SELECT_REACTOR_SIZE %d\n"), ACE_DEFAULT_SELECT_REACTOR_SIZE)); // Insert the vector of <ACE_HANDLE>s into the set. for (int i = 0; handle_vector[i] != ACE_INVALID_HANDLE; i++) { if (handle_vector[i] < (ACE_HANDLE) ACE_DEFAULT_SELECT_REACTOR_SIZE) { handle_set.set_bit (handle_vector[i]); set.insert (handle_vector[i]); } } int count = 0; for (ACE_Handle_Set_Iterator i2 (handle_set); (handle = i2 ()) != ACE_INVALID_HANDLE; ) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("obtained handle %d\n"), handle)); int done = set.remove (handle); ACE_ASSERT (done == 0); count++; } ACE_ASSERT (count == handle_set.num_set ()); }
int run_main (int, ACE_TCHAR *[]) { int r; int retval = 0; unsigned k; MyNode node (1); ACE_START_TEST (ACE_TEXT ("Unbounded_Set_Test")); ACE_Unbounded_Set<MyNode> ubs; if (ubs.size () != 0) { ACE_ERROR ((LM_ERROR, "Error: ubs.size () != 0\n")); retval = -1; } if (!ubs.is_empty ()) { ACE_ERROR ((LM_ERROR, "Error: !ubs.is_empty ()\n")); retval = -1; } // Insert a value. Immediately remove it. r = ubs.insert (node); if (r != 0) { ACE_ERROR ((LM_ERROR, "Error: r != 0\n")); retval = -1; } if (ubs.size () != 1) { ACE_ERROR ((LM_ERROR, "Error: ubs.size () != 1\n")); retval = -1; } r = ubs.remove (node); if (r != 0) { ACE_ERROR ((LM_ERROR, "Error: r != 0\n")); retval = -1; } if (ubs.size () != 0) { ACE_ERROR ((LM_ERROR, "Error: ubs.size () != 0\n")); retval = -1; } // Insert several different values. for (node.k = 1; node.k <= 5; node.k++) { r = ubs.insert (node); if (r != 0) { ACE_ERROR ((LM_ERROR, "Error: r != 0\n")); retval = -1; } if (ubs.size () != node.k) { ACE_ERROR ((LM_ERROR, "Error: ubs.size () != node.k\n")); retval = -1; } } // Test assigment of sets. // To do that, we also test some of the iterator methods. typedef ACE_Unbounded_Set<MyNode> MySet; MySet ubs2 = ubs; // Test a typedef of a set. if (ubs2.size() != ubs.size()) { ACE_ERROR ((LM_ERROR, "Error: ubs2.size() != ubs.size()\n")); retval = -1; } { MySet::ITERATOR it1 (ubs); MySet::iterator it2 (ubs2); for (k = 1; k <= 5; k++) { if (it1.done ()) { ACE_ERROR ((LM_ERROR, "Error: it1.done ()\n")); retval = -1; } if (it2.done ()) { ACE_ERROR ((LM_ERROR, "Error: it2.done ()\n")); retval = -1; } MyNode n1 = *it1; MyNode n2 = *it2; if (!(n1 == n2)) { ACE_ERROR ((LM_ERROR, "Error: !(n1 == n2)\n")); retval = -1; } it1.advance (); it2.advance (); } if (!it1.done ()) { ACE_ERROR ((LM_ERROR, "Error: !it1.done ()\n")); retval = -1; } if (!it2.done ()) { ACE_ERROR ((LM_ERROR, "Error: !it2.done ()\n")); retval = -1; } // Verify that a set may be emptied while an iterator on the set is // in-scope but inactive: ubs.reset (); // Restore original set from ubs2 ubs = ubs2; } // Selective deletion of elements and element retrieval. { MySet::iterator it (ubs2); int deleted = 0; while (! it.done ()) { MyNode n = *it; it.advance (); /* Being friendly here: Move the iterator on so that element removal does not interfere with the current iterator position. The less friendly case, removal under the current iterator position, is below. */ if (n.k % 2 == 1) { r = ubs2.remove (n); deleted++; } } if (ubs2.size () + deleted != ubs.size()) { ACE_ERROR ((LM_ERROR, "Error: ubs2.size () + deleted != ubs.size()\n")); retval = -1; } MyNode node2 (2); if (ubs2.find (node2) != 0) { ACE_ERROR ((LM_ERROR, "Error: ubs2.find (node2) != 0\n")); retval = -1; } MyNode node3 (3); if (ubs2.find (node3) == 0) { ACE_ERROR ((LM_ERROR, "Error: ubs2.find (node3) == 0\n")); retval = -1; } ubs2.insert (node3); } size_t s = count_const_set (ubs); if (s != ubs.size ()) { ACE_ERROR ((LM_ERROR, "Error: s != ubs.size ()\n")); retval = -1; } ACE_Unbounded_Set<MyNode> ubs_insert; MyNode node4 (4); if (ubs_insert.insert (node4) != 0) { ACE_ERROR ((LM_ERROR, "Error: insert node4 failed\n")); retval = -1; } if (ubs_insert.insert (node4) != 1) { ACE_ERROR ((LM_ERROR, "Error: insert node4 didn't return 1\n")); retval = -1; } // Test iterating through a set and deleting elements. { ACE_Unbounded_Set<MyNode*> ubs3; MyNode *n = 0; for (int i = 0; i < 10; ++i) { n = new MyNode (i); ubs3.insert (n); } MyNode **i_n = 0; ACE_Unbounded_Set_Iterator<MyNode*> ubs3_iter (ubs3.begin ()); for (; ubs3_iter.next (i_n); ++ubs3_iter) delete *i_n; } ACE_END_TEST; return retval; }
int run_main (int, ACE_TCHAR *[]) { int r; unsigned k; MyNode node (1); ACE_START_TEST (ACE_TEXT ("Unbounded_Set_Test")); ACE_Unbounded_Set<MyNode> ubs; ACE_ASSERT (ubs.size () == 0); // Insert a value. Immediately remove it. r = ubs.insert (node); ACE_ASSERT (r == 0); ACE_ASSERT (ubs.size () == 1); r = ubs.remove (node); ACE_ASSERT (r == 0); ACE_ASSERT (ubs.size () == 0); // Insert several different values. for (node.k = 1; node.k <= 5; node.k++) { r = ubs.insert (node); ACE_ASSERT (r == 0); ACE_ASSERT (ubs.size () == node.k); } // Test assigment of sets. // To do that, we also test some of the iterator methods. typedef ACE_Unbounded_Set<MyNode> MySet; MySet ubs2 = ubs; // Test a typedef of a set. ACE_ASSERT (ubs2.size() == ubs.size()); { MySet::ITERATOR it1 (ubs); MySet::iterator it2 (ubs2); for (k = 1; k <= 5; k++) { ACE_ASSERT (! it1.done ()); ACE_ASSERT (! it2.done ()); MyNode n1 = *it1; MyNode n2 = *it2; ACE_ASSERT (n1 == n2); it1.advance (); it2.advance (); } ACE_ASSERT (it1.done ()); ACE_ASSERT (it2.done ()); // Verify that a set may be emptied while an iterator on the set is // in-scope but inactive: ubs.reset (); // Restore original set from ubs2 ubs = ubs2; } // Selective deletion of elements and element retrieval. { MySet::iterator it (ubs2); int deleted = 0; while (! it.done ()) { MyNode n = *it; it.advance (); /* Being friendly here: Move the iterator on so that element removal does not interfere with the current iterator position. The less friendly case, removal under the current iterator position, is below. */ if (n.k % 2 == 1) { r = ubs2.remove (n); deleted++; } } ACE_ASSERT (ubs2.size () + deleted == ubs.size()); MyNode node2 (2); ACE_ASSERT (ubs2.find (node2) == 0); MyNode node3 (3); ACE_ASSERT (ubs2.find (node3) != 0); ubs2.insert (node3); } size_t s = count_const_set (ubs); ACE_ASSERT (s == ubs.size ()); // Test deletion under the cursor. // This is the regression test for Bugzilla bug 1460. { MySet::iterator end = ubs2.end (); for (MySet::iterator i = ubs2.begin (); i != end; i++) { r = ubs2.remove (*i); ACE_ASSERT (r == 0); } ACE_ASSERT (ubs2.size () == 0); } ACE_ASSERT (ubs2.is_empty ()); ACE_END_TEST; return 0; }
int Task_Entry::merge_frames (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries, Task_Entry &owner, ACE_Ordered_MultiSet <Dispatch_Entry_Link> &dest, ACE_Ordered_MultiSet <Dispatch_Entry_Link> &src, u_long &dest_period, u_long src_period, u_long number_of_calls, u_long starting_dest_sub_frame) { int status = 0; // reframe dispatches in the destination set to the new frame size // (expands the destination set's period to be the new enclosing frame) if (reframe (dispatch_entries, owner, dest, dest_period, ACE::minimum_frame_size (dest_period, src_period)) < 0) return -1; // use iterator for efficient insertion into the destination set ACE_Ordered_MultiSet_Iterator <Dispatch_Entry_Link> dest_iter (dest); // do virtual iteration over the source set in the new frame, adding // adjusted dispatch entries to the destination Dispatch_Proxy_Iterator src_iter (src, src_period, dest_period, number_of_calls, starting_dest_sub_frame); for (src_iter.first (starting_dest_sub_frame); src_iter.done () == 0; src_iter.advance ()) { // Policy: disjunctively dispatched operations get their // deadline and priority from the original dispatch - when and // if it is useful to change any of the merge policies, this // should be one of the decisions factored out into the // disjunctive merge strategy class. Dispatch_Entry *entry_ptr; ACE_NEW_RETURN (entry_ptr, Dispatch_Entry (src_iter.arrival (), src_iter.deadline (), src_iter.priority (), src_iter.OS_priority (), owner), -1); // if even one new dispatch was inserted, status is "something happened". status = 1; // add the new dispatch entry to the set of all dispatches, and // a link to it to the dispatch links for this task entry if (dispatch_entries.insert (entry_ptr) < 0) return -1; else if (dest.insert (Dispatch_Entry_Link (*entry_ptr), dest_iter) < 0) return -1; // TBD - Clients are not assigned priority, but rather obtain it // from their call dependencies. We could complain here if // there is a priority specified that doesn't match (or is lower // QoS?) } return status; }
int Task_Entry::conjunctive_merge (Dependency_Type dt, ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries, ACE_CString &unresolved_locals, ACE_CString &unresolved_remotes) { int result = 0; char string_buffer [BUFSIZ]; // Iterate over the dependencies, and determine the total frame // size. u_long frame_size = 1; ACE_Unbounded_Set_Iterator <Task_Entry_Link *> dep_iter (callers_); for (dep_iter.first (); dep_iter.done () == 0; dep_iter.advance ()) { Task_Entry_Link **link; if (dep_iter.next (link) == 0 || link == 0 || *link == 0) return -1; // The link matches the dependency type given. if ((*link)->dependency_type () == dt) { // Check for and warn about unresolved remote dependencies // in the ONE_WAY call graph. if ((*link)->dependency_type () == RtecBase::ONE_WAY_CALL && (*link)->caller ().has_unresolved_remote_dependencies () && ! this->has_unresolved_remote_dependencies ()) { // Propagate the unresolved remote dependency flag, and // issue a debug scheduler warning. this->has_unresolved_remote_dependencies (1); ORBSVCS_DEBUG ((LM_DEBUG, "Warning: an operation identified by " "\"%s\" has unresolved remote dependencies.\n", (const char*) this->rt_info ()->entry_point)); // Record entry point in list of unresolved remote // dependencies ACE_OS::sprintf (string_buffer, "// %s\n", (const char*) this->rt_info ()->entry_point); unresolved_remotes += ACE_CString (string_buffer); } // Check for and warn about unresolved local dependencies in // the ONE_WAY call graph. if ((*link)->dependency_type () == RtecBase::ONE_WAY_CALL && (*link)->caller ().has_unresolved_local_dependencies () && ! this->has_unresolved_local_dependencies ()) { // Propagate the unresolved local dependency flag, and // issue a debug scheduler warning. this->has_unresolved_local_dependencies (1); ORBSVCS_DEBUG ((LM_DEBUG, "Warning: an operation identified by " "\"%s\" has unresolved local dependencies.\n", (const char*) this->rt_info ()->entry_point)); // Record entry point in list of unresolved local dependencies ACE_OS::sprintf (string_buffer, "// %s\n", (const char*) this->rt_info ()->entry_point); unresolved_locals += ACE_CString (string_buffer); } frame_size = ACE::minimum_frame_size (frame_size, (*link)->caller ().effective_period_); } } // Reframe dispatches in the set to the new frame size (expands the // set's effective period to be the new enclosing frame). if (reframe (dispatch_entries, *this, dispatches_, effective_period_, frame_size) < 0) return -1; // A container and iterator for virtual dispatch sets over which the // conjunction will operate ACE_Ordered_MultiSet <Dispatch_Proxy_Iterator *> conj_set; ACE_Ordered_MultiSet_Iterator <Dispatch_Proxy_Iterator *> conj_set_iter (conj_set); // Iterate over the dependencies, and for each of the given call // type, create a Dispatch_Proxy_Iterator for the caller's dispatch // set, using the caller's period, the total frame size, and the // number of calls: if any of the sets is empty, just return 0; for (dep_iter.first (); dep_iter.done () == 0; dep_iter.advance ()) { Task_Entry_Link **link; if (dep_iter.next (link) == 0 || link == 0 || *link == 0) return -1; // The link matches the dependency type given. if ((*link)->dependency_type () == dt) { Dispatch_Proxy_Iterator *proxy_ptr; ACE_NEW_RETURN (proxy_ptr, Dispatch_Proxy_Iterator ((*link)->caller ().dispatches_, (*link)->caller ().effective_period_, frame_size, (*link)->number_of_calls ()), -1); // If there are no entries in the virtual set, we're done. if (proxy_ptr->done ()) return 0; else if (conj_set.insert (proxy_ptr, conj_set_iter) < 0) return -1; } } // loop, adding conjunctive dispatches, until one of the conjunctive // dispatch sources runs out of entries over the total frame conj_set_iter.first (); int more_dispatches = (conj_set_iter.done ()) ? 0 : 1; while (more_dispatches) { Time arrival = 0; Time deadline = 0; Preemption_Priority priority = 0; OS_Priority OS_priority = 0; for (conj_set_iter.first (); conj_set_iter.done () == 0; conj_set_iter.advance ()) { // initialize to earliest arrival and deadline, and highest priority arrival = 0; deadline = 0; priority = 0; OS_priority = 0; // Policy: conjunctively dispatched operations get the // latest deadline of any of the dispatches in the // conjunction at the time they were dispatched - when and // if it is useful to change any of the merge policies, this // should be one of the decisions factored out into the // conjunctive merge strategy class. // Policy: conjunctively dispatched operations get the // lowest priority of any of the dispatches in the // conjunction at the time they were dispatched - when and // if it is useful to change any of the merge policies, this // should be one of the decisions factored out into the // conjunctive merge strategy class. // Obtain a pointer to the current dispatch proxy iterator. Dispatch_Proxy_Iterator **proxy_iter; if (conj_set_iter.next (proxy_iter) == 0 || proxy_iter == 0 || *proxy_iter == 0) return -1; // Use latest arrival, latest deadline, lowest priority (0 is highest). if (arrival <= (*proxy_iter)->arrival ()) arrival = (*proxy_iter)->arrival (); if (deadline <= (*proxy_iter)->deadline ()) deadline = (*proxy_iter)->deadline (); if (priority <= (*proxy_iter)->priority ()) { priority = (*proxy_iter)->priority (); OS_priority = (*proxy_iter)->OS_priority (); } (*proxy_iter)->advance (); if ((*proxy_iter)->done ()) more_dispatches = 0; } Dispatch_Entry *entry_ptr; ACE_NEW_RETURN (entry_ptr, Dispatch_Entry (arrival, deadline, priority, OS_priority, *this), -1); // If even one new dispatch was inserted, result is "something // happened". result = 1; // Add the new dispatch entry to the set of all dispatches, and // a link to it to the dispatch links for this task entry. if (dispatch_entries.insert (entry_ptr) < 0) return -1; // Use iterator for efficient insertion into the dispatch set. ACE_Ordered_MultiSet_Iterator <Dispatch_Entry_Link> insert_iter (dispatches_); if (dispatches_.insert (Dispatch_Entry_Link (*entry_ptr), insert_iter) < 0) return -1; // TBD - Clients are not assigned priority, but rather obtain it // from their call dependencies. We could complain here if // there is a priority specified that doesn't match (or is lower // QoS?) } return result; }