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.
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.