#include <stdlib.h> // for exit, EXIT_FAILURE, EXIT_SUC... #include <atomic> // for atomic_thread_fence, memory_... #include <cstdint> // for uint64_t #include <iostream> // for operator<<, basic_ostream #include "Actor.hpp" // for Actor #include "CountingPrivateSemaphore.hpp" // for CPS #include "Debug.hpp" // for WDBG #include "Dispatcher.hpp" // for Dispatcher #include "Fiber.hpp" // for Fiber #include "Runtime.hpp" // for Runtime #include "emper-common.h" // for UNUSED_ARG #include "emper.hpp" // for spawn class SumActor : public Actor<uint64_t> { private: uint64_t sum = 0; protected: virtual void receive(uint64_t t) override { sum += t; } public: SumActor(Runtime& runtime) : Actor(runtime) {} uint64_t getSum() { std::atomic_thread_fence(std::memory_order::memory_order_acquire); return sum; } }; static void mainFiber(void* runtime_ptr) { Runtime& runtime = *(Runtime*)runtime_ptr; const unsigned int FIBER_COUNT = 1000; const uint64_t FIBERS_COUNT_TO = 1000; const uint64_t PER_FIBER_SUM = (FIBERS_COUNT_TO * (FIBERS_COUNT_TO + 1)) / 2; const uint64_t EXPECTED_SUM = FIBER_COUNT * PER_FIBER_SUM; SumActor sumActor(runtime); sumActor.start(); CPS cps; for (unsigned int i = 0; i < FIBER_COUNT; ++i) { spawn( [&sumActor] { WDBG(Dispatcher::getCurrentFiber() << " starts to count to " << FIBERS_COUNT_TO); for (uint64_t i = 1; i <= FIBERS_COUNT_TO; ++i) { sumActor.tell(i); } }, cps); } // Wait for the producer fibers to finish. cps.wait(); // Wait for the actor to become idle. bool actorIdle = sumActor.waitUntilIdle(60 * 1000); if (!actorIdle) { std::cerr << "FAILURE: Actor did not went idle"; exit(EXIT_FAILURE); } if (sumActor.getSum() != EXPECTED_SUM) { std::cerr << "FAILURE: Actor sum " << sumActor.getSum() << " is not equal to expected sum " << EXPECTED_SUM << std::endl; exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } int main(UNUSED_ARG int arg, UNUSED_ARG char* argv[]) { Runtime runtime; Fiber* fiber = Fiber::from(mainFiber, (void*)&runtime); runtime.schedule(*fiber); runtime.waitUntilFinished(); return EXIT_FAILURE; }