Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Unit resources

resource: true declares an indivisible resource. This model places each Thread under a ThreadPool, then places a running Task under the specific thread it claims.

YAML model

quent: alpha
model: unit_resource

entities:
  ThreadPool:
    events:
      created: {}

  Thread:
    resource: true
    events:
      registered:
        attributes:
          pool: { scope-ref: ThreadPool }

fsms:
  Task:
    states:
      running:
        initial: true
        attributes:
          # ThreadUsage is generated from the Thread resource declaration.
          thread: { scope-ref: Thread, data: ThreadUsage }
        to: [completed]
      completed: {}

The ThreadUsage record is generated automatically. It has no fields because a unit resource is claimed as a whole.

Instrumentation API

The generated API attaches the usage record to the scoped thread reference.

use instrumentation::{Context, Noop, Task, Thread, ThreadPool, ThreadUsage, UnitResource};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let context = Context::<UnitResource>::try_new(Noop)?;

    let mut pool = context.observer::<ThreadPool>().handle();
    pool.created()?;

    let mut thread = context.observer::<Thread>().handle();
    thread.registered(pool.as_entity_ref())?;

    let _task = context
        .observer::<Task>()
        .handle()
        .running(thread.as_entity_ref_with(ThreadUsage))
        .completed();

    Ok(())
}
#include "quent-tutorial-unit-resource-cpp-bridge/gen/quent.hpp"

int main() {
  auto context = quent::Context::none();
  auto pool = context.thread_pool_observer()->handle();
  pool.created();

  auto thread = context.thread_observer()->handle();
  thread.registered(quent::thread::Registered{.pool = pool.id()});

  auto running = context.task_observer()->handle().running(
      quent::task::Running{
          .thread = quent::refs::ThreadUsageRef{
              .target = thread.id(),
              .data = quent::records::ThreadUsage{},
          },
      });
  auto completed = std::move(running).completed();
  return 0;
}
import quent_tutorial_unit_resource as quent


def main() -> None:
    with quent.Context() as context:
        pool = context.thread_pool_observer().handle()
        pool.created()

        thread = context.thread_observer().handle()
        thread.registered(pool=pool)

        task = context.task_observer().handle()
        running = task.running(thread={"target": thread, "data": {}})
        completed = running.completed()


if __name__ == "__main__":
    main()
Key point

A unit resource represents one indivisible resource instance.

Check yourself

What does resource: true mean for Thread?

Which hierarchy does the model define?

Full code