Skip to content
Snippets Groups Projects
SimpleActorTest.cpp 1.78 KiB
#include <atomic>
#include <mutex>

#include "Actor.hpp"
#include "CountingPrivateSemaphore.hpp"
#include "Debug.hpp"
#include "Dispatcher.hpp"
#include "Runtime.hpp"
#include "emper.hpp"

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;
}