What will happen if an ACTOR has no wait statement

I’m using flow to write my own codes, and if the ACTOR has no wait statement, it will prompt a warning message “ACTOR xxx does not contain a wait() statement”, so I don’t know if it’s safe to just have ACTOR that does not contain a wait() statement

If an ACTOR has no wait() statement, then it should be declared as a normal function, which executes without blocking. ACTOR should be used to encapsulate async functions.

Specifically, the ACTOR compiler will translate an actor into 2 C++ classes and a function, with automatically generated callbacks and their invocations when a future is ready.

1 Like

As @jzhou pointed out, you should not use ACTOR for functions without any wait statements as there is some overhead.

In addition to the 2 generated classes, calling an actor will create an object on the heap. It’s also a bit weird: when returning from an ACTOR Future<T> ... function, you must return something of type T and not Future<T>.

Reading the generated code shouldn’t be too hard and I would recommend you do that. For example:

ACTOR Future<Void> foo() {
	return Void();
}

This actor with no wait statement will result in this code

// This generated class is to be used only via foo()
class FooActor final : public Actor<Void>, public FastAllocated<FooActor>, public FooActorState<FooActor> {
public:
	using FastAllocated<FooActor>::operator new;
	using FastAllocated<FooActor>::operator delete;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdelete-non-virtual-dtor"
	void destroy() override { ((Actor<Void>*)this)->~Actor(); operator delete(this); }
#pragma clang diagnostic pop
	FooActor() 
		 : Actor<Void>(),
		   FooActorState<FooActor>()
	{
		#ifdef ENABLE_SAMPLING
		this->lineage.setActorName("foo");
		LineageScope _(&this->lineage);
		#endif
		this->a_body1();

	}
	void cancel() override
	{
		auto wait_state = this->actor_wait_state;
		this->actor_wait_state = -1;
		switch (wait_state) {
		}

	}
};
}
[[nodiscard]] Future<Void> foo(  ) {
	return Future<Void>(new FooActor());
}

As you can see, there’s quite some overhead. An equivalent function would be:

Future<Void> foo() {
	return Void();
}

Which will be much cheaper.

1 Like