6.4 Summary
concurrency options
- Consider using protected objects to provide mutually exclusive access to data.
- Consider using protected objects to control or synchronize access to data shared by multiple tasks .
- Consider using protected objects to implement synchronization, such as a passive resource monitor.
- Consider encapsulating protected objects in the private part or body of a package.
- Consider using a protected procedure to implement an interrupt handler.
- Do not attach a protected procedure handler to a hardware interrupt if that interrupt has a maximum priority greater than the ceiling priority assigned to the handler.
- Avoid the use of global variables in entry barriers.
- Avoid the use of barrier expressions with side effects.
- Use tasks to model selected asynchronous threads of control within the problem domain.
- Consider using tasks to define concurrent algorithms.
- Consider using rendezvous when your application requires synchronous unbuffered communication.
- Consider using discriminants to minimize the need for an explicit initialization operation (Rationale 1995, §9.1).
- Consider using discriminants to control composite components of the protected objects, including setting the size of an entry family (Rationale 1995, §9.1).
- Consider using a discriminant to set the priority of a protected object (Rationale 1995, §9.1).
- Consider using a discriminant to identify an interrupt to a protected object (Rationale 1995, §9.1).
- Consider declaring a task type with a discriminant to indicate
(Rationale 1995, §9.6):
- Priority, storage size, and size of entry families of individual tasks of a type
- Data associated with a task (through an access discriminant)
- Consider using single task declarations to declare unique instances of concurrent tasks.
- Consider using single protected declarations to declare unique instances of protected objects.
- Minimize dynamic creation of tasks because of the potentially high startup overhead; reuse tasks by having them wait for new work on some appropriate entry queue.
- Do not rely on pragma Priority unless your compiler supports the Real-Time Annex (Ada Reference Manual 1995, Annex D) and priority scheduling.
- Minimize risk of priority inversion by use of protected objects and ceiling priority.
- Do not rely upon task priorities to achieve a particular sequence of task execution.
- Do not depend on a particular delay being achievable (Nissen and Wallis 1984).
- Use a delay until not a delay statement to delay until a specific time has been reached.
- Avoid using a busy waiting loop instead of a delay.
- Carefully consider the placement of components of protected types within a tagged type inheritance hierarchy.
- Consider using generics to provide extensibility of data types requiring the restrictions provided by protected objects.
communication
- Minimize the work performed during a rendezvous .
- Minimize the work performed in the selective accept loop of a task.
- Consider using protected objects for data synchronization and communication.
- Provide a handler for exception Program_Error whenever you cannot avoid a selectiveaccept statement whose alternatives can all be closed (Honeywell 1986).
- Make systematic use of handlers for Tasking_Error.
- Be prepared to handle exceptions during a rendezvous .
- Consider using a when others exception handler.
- Do not depend on the values of the task attributes 'Callable or 'Terminated (Nissen and Wallis 1984).
- Do not depend on attributes to avoid Tasking_Error on an entry call.
- For tasks, do not depend on the value of the entry attribute 'Count.
- Using the 'Count attribute with protected entries is more reliable than using the 'Count attribute with task entries.
- Use calls on protected subprograms or entries to pass data between tasks rather than unprotected shared variables.
- Do not use unprotected shared variables as a task synchronization device.
- Do not reference nonlocal variables in a guard .
- If an unprotected shared variable is necessary, use the pragma Volatile or Atomic.
- Use caution with conditional entry calls to task entries.
- Use caution with selective accepts with else parts.
- Do not depend upon a particular delay in timed entry calls to task entries.
- Do not depend upon a particular delay in selective accepts with delay alternatives.
- Consider using protected objects instead of the rendezvous for data-oriented synchronization.
- Minimize the number of accept and select statements per task .
- Minimize the number of accept statements per entry.
termination
- Consider using an exception handler for a rendezvous within the main loop inside each task.
- Do not create nonterminating tasks unintentionally.
- Explicitly shut down tasks that depend on library packages.
- Confirm that a task is terminated before freeing it with Ada.Unchecked_Deallocation.
- Consider using a select statement with a terminate alternative rather than an accept statement alone.
- Consider providing a terminate alternative for every selective accept that does not require an else part or a delay.
- Do not declare or create a task within a user-defined Finalize procedure after the environment task has finished waiting for other tasks.
- Avoid using the abort statement.
- Consider using the asynchronous select statement rather than the abort statement.
- Minimize uses of the asynchronous select statement.
- Avoid assigning nonatomic global objects from a task or from the abortable part of an asynchronous select statement.
- Place an exception handler for others at the end of a task body.
- Consider having each exception handler at the end of a task body report the task's demise.
- Do not rely on the task status to determine whether a rendezvous can be made with the task.
- Do not call a task entry that directly or indirectly results in a call to an entry of the original calling task.
- Avoid race conditions in setting an exit status code from the main program when using the procedure Ada.Command_Line.Set_Exit_Status.
- In a program with multiple tasks, encapsulate, serialize, and check calls to the procedure Ada.Command_Line.Set_Exit_Status.
note
This page of the "Ada Quality and Style Guide" has been adapted from the original work at https://en.wikibooks.org/wiki/Ada_Style_Guide, which is licensed under the Creative Commons Attribution-ShareAlike License; additional terms may apply. Page not endorsed by Wikibooks or the Ada Style Guide Wikibook authors. This page is licensed under the same license as the original work.