예제 #1
0
TEST_F(CoreContextTest, TerminatedContextHarmless) {
  AutoCurrentContext ctxt;
  ctxt->Initiate();
  AutoRequired<TriesToCreateChild>{};
  ctxt->SignalShutdown();
  ASSERT_THROW(ctxt->Create<void>(), dispatch_aborted_exception) << "An exception should have been thrown when attempting to create a child from a terminated context";
}
예제 #2
0
int main(){
  
  // The 2 main thread classes in Autowiring are the BasicThread and CoreThread.
  // Classes that inherit from these types will have thread capabilities
  // Both start when their enclosing context is 'initiated'. Threads injected
  // after the context is initiated will start immediatly
  
  AutoRequired<MyBasicThread> myBasic;
  
  AutoCurrentContext ctxt;
  ctxt->Initiate(); // myBasic->Run() starts now in its own thread
  
  std::this_thread::sleep_for(std::chrono::milliseconds(250));
  
  std::cout << "injecting a CoreThread" << std::endl;
  
  // Types inheriting from CoreThread implement a dispatch queue in their 'run()'
  // function. Lambdas can be appended with operator+=
  
  AutoRequired<MyCoreThread> myCore;
  myCore->AddToQueue(42);
  myCore->AddToQueue(1337);
  
  *myCore += []{
    std::cout << "This gets run after '1337'" << std::endl;
  };
  
  // This should be run before 'myCore' is finished
  std::cout << "This thread is faster\n";
  
  // This will wait for all outstanding threads to finish before terminating the context
  ctxt->SignalShutdown(true);
}
예제 #3
0
TEST_F(AutoPacketFactoryTest, AutoPacketStatistics) {
  // Create a context, fill it up, kick it off:
  AutoCurrentContext ctxt;
  AutoRequired<DelaysAutoPacketsOneMS> dapoms;
  AutoRequired<AutoPacketFactory> factory;
  ctxt->Initiate();

  int numPackets = 20;

  // Send 20 packets which should all be delayed 1ms
  for (int i = 0; i < numPackets; ++i) {
    auto packet = factory->NewPacket();
    packet->Decorate(i);
  }

  // Shutdown our context, and rundown our factory
  ctxt->SignalShutdown();
  factory->Wait();

  // Ensure that the statistics are not too wrong
  // We delayed each packet by one ms, and our statistics are given in nanoseconds
  double packetDelay = (double) std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds(1)).count();
  ASSERT_EQ(numPackets, factory->GetTotalPacketCount()) << "The factory did not get enough packets";

  ASSERT_LE(packetDelay, factory->GetMeanPacketLifetime()) << "The mean packet lifetime was less than the delay on each packet";
}
예제 #4
0
TEST_F(AutoPacketFactoryTest, IsRunningWhilePacketIssued) {
  AutoCurrentContext ctxt;
  ctxt->Initiate();
  AutoRequired<AutoPacketFactory> factory;
  auto packet = factory->NewPacket();
  ctxt->SignalShutdown();
  ASSERT_TRUE(factory->IsRunning()) << "Factory should be considered to be running as long as packets are outstanding";
}
예제 #5
0
TEST_F(CoreContextTest, AwaitWithShutdown) {
  AutoCurrentContext x;
  std::thread killer{
    [x] {
      std::this_thread::sleep_for(std::chrono::milliseconds{ 1 });
      x->SignalShutdown();
    }
  };

  ASSERT_THROW(x->Await<ChildListener>(), dispatch_aborted_exception) << "A context was terminated during await but did not throw as expected";
  killer.join();
}
예제 #6
0
TEST_F(IPCMessagingTest, SequentialMessageTransmission)
{
  AutoCurrentContext ctxt;
  std::string ns = GenerateNamespaceName();

  // Create client and server
  AutoConstruct<IPCClient> client(IPCTestScope(), ns.c_str());
  AutoConstruct<IPCListener> listener(IPCTestScope(), ns.c_str());

  auto val = std::make_shared<std::promise<int>>();
  listener->onClientConnected += [&val](const std::shared_ptr<IPCEndpoint>& ep) {
    AutoCreateContext ctxt;
    ctxt->Add(ep);

    auto channel = ep->AcquireChannel(0, IPCEndpoint::Channel::READ_ONLY);
    int nMessages = 0;
    while (!ep->IsClosed()) {
      auto buffers = channel->ReadMessageBuffers();
      if (buffers.size() != 4)
        break;
      nMessages++;
    }
    val->set_value(nMessages);
  };

  auto ep = client->Connect(std::chrono::minutes(1));
  ASSERT_NE(nullptr, ep) << " Failed to connect in time";

  {
    auto channel = ep->AcquireChannel(0, IPCEndpoint::Channel::WRITE_ONLY);
    for (uint32_t i = 0; i < 300; i++) {
      Message message{ i, i + 1, i + 2, i + 3 };
      channel->Write(&message, sizeof(message));
      channel->Write(&message, sizeof(message));
      channel->Write(&message, sizeof(message));
      channel->Write(&message, sizeof(message));

      // Indicate that the entire message has been written
      channel->WriteMessageComplete();
    }
  }

  // Close connection, shut down context:
  ep.reset();
  ctxt->SignalShutdown();

  // Block until gatherer stops:
  auto f = val->get_future();
  ASSERT_EQ(std::future_status::ready, f.wait_for(std::chrono::minutes(1))) << "Server did not receive messages in a timely fashion";
  ASSERT_EQ(300, f.get()) << "Not all messages were received as expected";
}
예제 #7
0
TEST_F(CoreContextTest, AppropriateShutdownInterleave) {
  // Need both an outer and an inner context
  AutoCurrentContext ctxtOuter;
  AutoCreateContext ctxtInner;

  // Need to inject types at both scopes
  AutoRequired<ExplicitlyHoldsOutstandingCount> outer(ctxtOuter);
  AutoRequired<ExplicitlyHoldsOutstandingCount> inner(ctxtInner);

  // Start both contexts up
  ctxtOuter->Initiate();
  ctxtInner->Initiate();

  // Now shut down the outer context.  Hand off to an async, we want this to block.
  std::thread holder{
    [ctxtOuter] {
      ctxtOuter->SignalShutdown(true);
    }
  };
  auto holderClean = MakeAtExit([&holder] { holder.join(); });

  // Need to ensure that both outstanding counters are reset at some point:
  {
    auto cleanup = MakeAtExit([&] {
      outer->Proceed();
      inner->Proceed();
    });

    // Outer entry should have called "stop":
    auto future = outer->calledStop.get_future();
    ASSERT_EQ(
      std::future_status::ready,
      future.wait_for(std::chrono::seconds(5))
    ) << "Outer scope's OnStop method was incorrectly blocked by a child context member taking a long time to shut down";
  }

  // Both contexts should be stopped now:
  ASSERT_TRUE(ctxtOuter->Wait(std::chrono::seconds(5))) << "Outer context did not tear down in a timely fashion";
  ASSERT_TRUE(ctxtOuter->IsQuiescent()) << "Quiescence not achieved by outer context after shutdown";
  ASSERT_TRUE(ctxtInner->Wait(std::chrono::seconds(5))) << "Inner context did not tear down in a timely fashion";
}