How to return a result from an active object state machine

I frequently use the concept of Active Objects (https://www.state-machine.com/active-object) combined with state machines when designing code. The key idea behind these is that only “events” are fed into (and out of) an object and state machines “react to” these events. This leads to a very different type of design from a sequential program. Whereas a sequential program is designed in a “do this, then this returning some results, then do something with those results, …” an active object/event-based design is “when event A happens do this and emit event B.”

This works great for the vast majority of problems, but I occasionally get stuck when I need to “retrieve” some value from an active object/state machine. Let me illustrate with a simple example.

Suppose I am designing a toaster state machine.

Incoming Events:

  • Set Temperature
  • Insert Bread
  • Remove Bread
  • Start
  • Stop

Outgoing Events:

  • Started
  • Stopped
  • Done

Essentially, the toaster (and any active state machine) is a “black box” which can be interacted with by “dispatching” events to it and responding to events “emitted” by it.

Now, imagine Person A interacts with the toaster by setting the temperature and starting it. This person leaves and Person B steps up to the toaster. Since Person B did not perform the original interactions with the toaster, they have no knowledge of what the toaster is doing. Thus, this person wants some way to “query” the internal state of the toaster to make some decision. For example, what if Person B is very inquisitive and would like to know the internal temperature of the toaster right now.

This third type of interaction, “query”, is the very essence of sequential programming (via return values) but seems foreign to event-based design. To me, since a state machine should be a black box that is only recognizable by its interactions to the outside, “getting” a value “returned” from a state machine is essentially breaking into this black box to look at the internal state. That being said, I still find that I need to do it (perhaps this is a design problem).

One solution I have used is the idea of “callbacks.” This transforms the synchronous query into an asynchronous one. You are essentially telling the state machine, “I would like some information, let me know via this callback when you have it.”

stateMachine.getSomething([](int result){
    //Do something with result
});

While this works, it can result in very complex chains of callbacks and requires a fair amount of dynamic memory allocation making it unfriendly for embedded systems.

Another solution would be the idea of “futures” and “promises.” (I apologize if I get the terminology slightly wrong as I have never actually used this pattern.) The “getter” method would “return” a “promise” immediately on which the caller will block waiting for a result. Meanwhile, the asynchronous active state machine will perform the processing necessary to get the result. When finished, it will place the value in the future/promise object allowing the caller to continue. In this way, the caller is written in a traditional, sequential, call-and-return fashion, while the state machine remains unchanged.

auto future = statemachine.getSomething();
auto value = future.get(); //Will block here

The main problem here is the requirement that the state machine must be running within a different thread from the caller otherwise a deadlock will result. In other words, if a state machine were to block on a future from another state machine, these state machines would have to be on different threads. Again, a thread for every object is very resource intensive and not so suitable for embedded systems.

Are there other solutions? I admit that I may be hybridizing sequential and event-based programming in my head, but I fail to think of another solution to this type of problem. I would appreciate resources to any helpful reading on this topic.

5

Taking your toaster example, I would label what you are doing a “Single Threaded Apartment”

Specifically by only using a single thread to service the toaster object, you effectively get thread safety for free – in there can never be two threads mutating the state since there is only one thread in the apartment. Further unless you explicitly hand back control to the outer (event) loop you don’t have to worry about overlapping message processing (typically the code completes the handling of one message before moving on to the next) – to put it another way; reentrancy isn’t possible either.

If you allow direct access to the objects state (even if the querying thread is read-only) you break your encapsulation in that the reader thread may see a partial/incorrect state, if the state is being mutated by the primary servicing thread (at the same time).

The solution to this, is that all query operations have to be handled/serviced via the event loop, so that they are made on the primary servicing thread.

This is an old problem (I would suggest reading up on the Microsoft COM model) specifically in COM this would be known as “Inter thread marshaling”.

Specifically there are only really two possibilities:

Query from the Event Thread

For various reasons it is possible that the query is coming in on the correct thread (this typically only happens if you have invoked an external callback from the primary event loop thread).

In such cases you don’t need to Marshal the call you can just directly access the state **

** – There are a few caveats here, the primary one being that you need to ensure that all places where you provide outbound/callbacks that the state is valid before making the outbound call so that if the external code uses the primary thread to make a query, the state of the Toaster will still be valid.

Query from a different Thread

In this case the a message is placed on the event loop and the external thread is blocked. Once the Toaster completes processing of all previous events it will service the query on the primary thread.
It can then pass the result back to the (blocked) querying thread and release the blocked thread.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật