Skip to content
Snippets Groups Projects
SimpleActorTest.cpp 2.47 KiB
Newer Older
  • Learn to ignore specific revisions
  • // SPDX-License-Identifier: LGPL-3.0-or-later
    
    // Copyright © 2020-2021 Florian Schmaus
    #include <atomic>		 // for atomic_thread_fence, memory_...
    #include <cstdint>	 // for uint64_t
    #include <cstdlib>	 // for exit, EXIT_FAILURE, EXIT_SUC...
    #include <iostream>	 // for operator<<, basic_ostream
    
    
    #include "Actor.hpp"										 // for Actor
    #include "CountingPrivateSemaphore.hpp"	 // for CPS
    
    #include "Dispatcher.hpp"								 // for Dispatcher
    
    #include "Fiber.hpp"										 // for Fiber
    #include "Runtime.hpp"									 // for Runtime
    #include "emper-common.h"								 // for UNUSED_ARG
    
    #include "emper-config.h"								 // // IWYU pragma: keep
    
    #include "emper.hpp"										 // for spawn
    
    
    class SumActor : public Actor<uint64_t> {
    
    	void receive(uint64_t t) override { sum += t; }
    
     public:
    	SumActor(Runtime& runtime) : Actor(runtime) {}
    
    	[[nodiscard]] auto getSum() const -> uint64_t {
    
    		std::atomic_thread_fence(std::memory_order_acquire);
    
    
    	void stop() { Actor::stop(); }
    
    };
    
    static void mainFiber(void* runtime_ptr) {
    
    	Runtime& runtime = *(Runtime*)runtime_ptr;
    
    	const unsigned int FIBER_COUNT = EMPER_LOG_LEVEL > Info ? 500 : 2500;
    
    	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();
    
    
    Florian Schmaus's avatar
    Florian Schmaus committed
    	CPS cps;
    
    	for (unsigned int fiberNum = 0; fiberNum < FIBER_COUNT; ++fiberNum) {
    
    					DBG(Dispatcher::getCurrentFiber()
    							<< " (" << fiberNum << ") 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);
    
    	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);
    }
    
    
    auto main(UNUSED_ARG int arg, UNUSED_ARG char* argv[]) -> int {
    
    	Fiber* fiber = Fiber::from(mainFiber, (void*)&runtime);
    
    	runtime.scheduleFromAnywhere(*fiber);
    
    
    	runtime.waitUntilFinished();
    
    	return EXIT_FAILURE;
    }