bool hopcroft_karp_bfs(testcase t) { fifo q = fifo_create(); fifo_item item; int v, u; /* for each v in G1 */ for(v=1; v<t->num_students+1; v++) { /* if Pair_G1[v] == NIL */ if(t->pair_g1[v] == NIL) { /* Dist[v] = 0 */ t->dist[v] = 0; /* Enqueue(Q, v) */ fifo_queue(q, v); } /* else */ else { /* Dist[v] = INFINITE */ t->dist[v] = INFINITE; } } /* Dist[NIL] = INFINITE */ t->dist[NIL] = INFINITE; /* while Empty(Q) == false */ while(q->size != 0) { /* v = Dequeue(Q) */ v = fifo_dequeue(q); /* if Dist[v] < Dist[NIL] */ if(t->dist[v] < t->dist[NIL]) { /* for each u in Adv[v] */ for(item = t->adjacencies[v]->first; item != NULL; item = item->next) { u = item->value; /* if Dist[ Pair_G2[u] ] == INFINITE */ if(t->dist[t->pair_g2[u]] == INFINITE) { /* Dist{ Pair_G2[u] ] = Dist[v] + 1 */ t->dist[t->pair_g2[u]] = t->dist[v] + 1; /* Enqueue(Q, Pair_G2[u]) */ fifo_queue(q, t->pair_g2[u]); } } } } /* return Dist[NIL] != INFINITE */ fifo_destroy(q); return (t->dist[NIL] != INFINITE); }
TEST(JobQueue, Priority) { JobQueue<int> fifo_queue(1, 0, false, INT_MAX, 30, 3); fifo_queue.enqueue(1); fifo_queue.enqueue(2); fifo_queue.enqueue(3, 2); fifo_queue.enqueue(4, 0); fifo_queue.enqueue(5, 1); fifo_queue.enqueue(6, 2); bool expired; EXPECT_EQ(3, fifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_EQ(6, fifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_EQ(5, fifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_EQ(1, fifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_EQ(2, fifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_EQ(4, fifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); }
void TestQueueRemovesAndCreatesDirectories() throw (Exception) { FileFinder checkpoints("checkpoints2", RelativeTo::ChasteTestOutput); // Remove directory in case it was there from previous executions. PetscTools::Barrier("TestQueueRemovesAndCreatesDirectories-0"); if (PetscTools::AmMaster()) { ABORT_IF_THROWS(checkpoints.Remove()); } PetscTools::Barrier("TestQueueRemovesAndCreatesDirectories-1"); TS_ASSERT(!checkpoints.Exists()); PetscTools::Barrier("TestQueueRemovesAndCreatesDirectories-2"); OutputDirectoryFifoQueue fifo_queue("checkpoints2", 2); TS_ASSERT(checkpoints.IsDir()); fifo_queue.CreateNextDir("0.1"); FileFinder dir1("0.1", checkpoints); TS_ASSERT(dir1.IsDir()); fifo_queue.CreateNextDir("0.2"); FileFinder dir2("0.2", checkpoints); TS_ASSERT(dir2.IsDir()); TS_ASSERT(dir1.IsDir()); PetscTools::Barrier("TestQueueRemovesAndCreatesDirectories-3"); fifo_queue.CreateNextDir("0.3"); FileFinder dir3("0.3", checkpoints); TS_ASSERT(dir3.IsDir()); TS_ASSERT(dir2.IsDir()); TS_ASSERT(!dir1.Exists()); PetscTools::Barrier("TestQueueRemovesAndCreatesDirectories-4"); fifo_queue.CreateNextDir("0.4"); FileFinder dir4("0.4", checkpoints); TS_ASSERT(dir4.IsDir()); TS_ASSERT(dir3.IsDir()); TS_ASSERT(!dir2.Exists()); TS_ASSERT(!dir1.Exists()); }
TEST(JobQueue, Expiration) { timespec timeOk; clock_gettime(CLOCK_MONOTONIC, &timeOk); timespec timeExpired = timeOk; timeExpired.tv_sec += 31; { JobQueue<int> fifo_queue(1, 0, false, INT_MAX, 30000); fifo_queue.enqueue(1); fifo_queue.enqueue(2); fifo_queue.enqueue(3); bool expired = false; EXPECT_EQ(1, fifo_queue.dequeueMaybeExpiredImpl(0, 0, true, timeOk, &expired)); EXPECT_FALSE(expired); EXPECT_EQ(2, fifo_queue.dequeueMaybeExpiredImpl(0, 0, true, timeExpired, &expired)); EXPECT_TRUE(expired); EXPECT_EQ(3, fifo_queue.dequeueMaybeExpiredImpl(0, 0, true, timeOk, &expired)); EXPECT_FALSE(expired); } { JobQueue<int> lifo_queue(1, 0, false, 0, 30000); lifo_queue.enqueue(1); lifo_queue.enqueue(2); lifo_queue.enqueue(3); bool expired = false; EXPECT_EQ(3, lifo_queue.dequeueMaybeExpiredImpl(0, 0, true, timeOk, &expired)); EXPECT_FALSE(expired); // now we should get a job from the beginning of the queue even though we // are in lifo mode before request expiration is enabled. EXPECT_EQ(1, lifo_queue.dequeueMaybeExpiredImpl(0, 0, true, timeExpired, &expired)); EXPECT_TRUE(expired); EXPECT_EQ(2, lifo_queue.dequeueMaybeExpiredImpl(0, 0, true, timeOk, &expired)); EXPECT_FALSE(expired); } { // job reaper. JobQueue<int> lifo_queue(1, 0, false, 0, 30000); lifo_queue.enqueue(1); lifo_queue.enqueue(2); lifo_queue.enqueue(3); lifo_queue.enqueue(4); lifo_queue.enqueue(5); // manipulate m_jobs timestamp to simulate time passing. lifo_queue.m_jobQueues[0][0].second.tv_sec -= 32; lifo_queue.m_jobQueues[0][1].second.tv_sec -= 31; // having job reaper should not affect anything other threads are doing. { bool expired = false; EXPECT_EQ(1, lifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_TRUE(expired); EXPECT_EQ(2, lifo_queue.dequeueMaybeExpired(1, 0, true, &expired)); EXPECT_TRUE(expired); } // now no more jobs are expired. job reaper would block. std::atomic<int> value(-1); std::thread thread([&]() { bool expired; value.store(lifo_queue.dequeueMaybeExpired(1, 0, true, &expired)); }); EXPECT_EQ(-1, value.load()); // even if you notify it. lifo_queue.notify(); EXPECT_EQ(-1, value.load()); { // but normal workers should proceed. bool expired = false; EXPECT_EQ(5, lifo_queue.dequeueMaybeExpired(0, 0, true, &expired)); EXPECT_FALSE(expired); } // now set the first job to be expired. lifo_queue.m_jobQueues[0][0].second.tv_sec -= 32; lifo_queue.notify(); // busy wait until value is updated. thread.join(); EXPECT_EQ(3, value.load()); // stop case bool exceptionCaught = false; std::thread thread1([&]() { bool expired; try { lifo_queue.dequeueMaybeExpired(1, 0, true, &expired); } catch (const JobQueue<int>::StopSignal&) { exceptionCaught = true; } }); lifo_queue.stop(); thread1.join(); EXPECT_TRUE(exceptionCaught); } }
void testcase_add_edge(testcase t, int student, int job) { fifo_queue(t->adjacencies[student_index(t, student)], job_index(t, job)); fifo_queue(t->adjacencies[job_index(t, job)], student_index(t, student)); }