Class serializer

Class Documentation

class concore::v1::serializer

Executor type that allows only one task to be executed at a given time.

If the main purpose of other executors is to define where and when tasks will be executed, the purpose of this executor is to introduce constrains between the tasks enqueued into it.

Given N tasks to be executed, the serializer ensures that there are no two tasks executed in parallel. It serializes the executions of this task. If a tasks starts executing all other tasks enqueued into the serializer are put on hold. As soon as one task is completed a new task is scheduled for execution.

As this executor doesn’t know to schedule tasks for executor it relies on one or two given executors to do the scheduling. If a base_executor is given, this will be the one used to schedule for execution of tasks whenever a new task is enqueued and the pool on on-hold tasks is empty. E.g., whenever we enqueue the first time in the serializer. If this is not given, the global_executor will be used.

If a cont_executor is given, this will be used to enqueue tasks after another task is finished; i.e., enqueue the next task. If this is not given, the serializer will use the base_executor if given, or spawn_continuation_executor.

A serializer in a concurrent system based on tasks is similar to mutexes for traditional synchronization-based concurrent systems. However, using serializers will not block threads, and if the application has enough other tasks, throughput doesn’t decrease.

Guarantees:

  • no more than 1 task is executed at once.

  • the tasks are executed in the order in which they are enqueued.

See

any_executor, global_executor, spawn_continuation_executor, n_serializer, rw_serializer

Public Functions

serializer(any_executor base_executor = {}, any_executor cont_executor = {})

Constructor.

If

base_executor is not given, global_executor will be used. If cont_executor is not given, it will use base_executor if given, otherwise it will use spawn_continuation_executor for enqueueing continuations.
Parameters
  • base_executor: Executor to be used to enqueue new tasks

  • cont_executor: Executor that enqueues follow-up tasks

The first executor is used whenever new tasks are enqueued, and no task is in the wait list. The second executor is used whenever a task is completed and we need to continue with the enqueueing of another task. In this case, the default, spawn_continuation_executor tends to work better than global_executor, as the next task is picked up immediately by the current working thread, instead of going over the most general flow.

See

global_executor, spawn_continuation_executor

template<typename F>
void execute(F &&f) const

Executes the given functor as a task in the context of the serializer.

If there are no tasks in the serializer, the given functor will be enqueued as a task in the

base_executor given to the constructor (default is global_executor). If there are already other tasks in the serializer, the given functor/task will be placed in a waiting list. When all the previous tasks are executed, this task will also be enqueued for execution.
Parameters
  • f: The functor to be executed

void execute(task t) const

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

void set_exception_handler(except_fun_t except_fun)

Sets the exception handler for enqueueing tasks.

The exception handler set here will be called whenever an exception is thrown while enqueueing a follow-up task. It will not be called whenever the task itself throws an exception; that will be handled by the exception handler set in the group of the task.

Parameters
  • except_fun: The function to be called whenever an exception occurs.

Cannot be called in parallel with task enqueueing and execution.

See

task_group::set_exception_handler

Friends

friend bool operator==(serializer l, serializer r)

Equality operator.

friend bool operator!=(serializer l, serializer r)

Inequality operator.