The Hive design pattern simply encapsulates running multiple threads of execution — it's as simple as that. A Hive object manages the execution of resident objects. A resident object should have a click method. Residents can be sheltered and removed from the Hive, and they can be started and stopped. When in the started state, the click method of a resident is called repeatedly by the Hive. The click method indicates through its boolean return value whether the resident should be called again in the next round. If not, the resident can be woken by external means later to put it back in the pool of running residents. A harness is responsible for creating the Hive and the various residents, sheltering them and managing the overall flow. The following figure is a representation of a Hive, harness and three residents.
The sequence diagram below shows the basic calling sequence required to operate a Hive.
Most operating systems do threading very well and the hive relies on it. An extra abstraction was deemed necessary for two reasons: first, to guarantee of time consistency across the multiple residents; second, so that the model is abstract enough for the implementation to be changed easily in order to incorporate different threading models easily without affecting the higher layers of the design stack.
Time consistency is provided by guaranteeing that the click method is called fairly uniformly across all residents. This ensures that the different time lines of the residents are more or less in sync.
The order in which the click method is called on different residents by the Hive is random, or, at least, unpredictable from the point of view of the residents. This is very similar to how OSes schedule threads today, of course. However, in the context of Monod, where individual residents play a role more akin to subroutines than to threads, this randomness is significant. We will revisit it in due time. The Hive, as a design pattern, needs much support in order to be actually useful. Specifically, it needs residents and a harness. We've already discussed the residents. The harness is also essential. It performs different roles:
The Hive abstraction is flexible enough to allow for many different implementations. For instance, the residents can run in a single OS thread, with the Hive acting as scheduler; or the residents can be spread across multiple threads (possibly one per resident); or they can be spread across multiple machines. Indeed, the current implementation of the Hive is the first example just cited, is an extremely lightweight implementation which does not consume much OS resources. In Monod, all the residents are very simple and require very little processing power, but fairly constant attention. However, if all goes well and Monod is indeed interesting, the plan is to expand it to a multi-platform implementation with remote method invocations. Much of the work would be concentrated in the Hive, and not in the rest of the design stack.
The residents individually do not need to be thread-safe — the click method will always return before being called again on the same resident. However, a resident should not assume anything about other residents since, as described above, there could be many threads running.
Hence, the Hive captures the essentially parallel aspect of the Cytoplasm. “Parallel” because many operations are conceivably happening at the same time. “Essentially” because the parallelism needs to be flattened or serialized to run on a standard computer.