Sometimes it is necessary to represent a simple data type with an optional boolean information that indicates whether the value is valid or just null. The concept of nullable type is often used in databases but also in JSON data representation. The Util.Nullables package provides several standard type to express the null capability of a value.
By default a nullable instance is created with the null flag set.
Util.Texts.Builders generic package was designed to provide string builders.
The interface was designed to reduce memory copies as much as possible.
Buildertype holds a list of chunks into which texts are appended.
- The builder type holds an initial chunk whose capacity is defined when the builder instance is declared.
- There is only an
Appendprocedure which allows to append text to the builder. This is the only time when a copy is made.
- The package defines the
Iterateoperation that allows to get the content collected by the builder. When using the
Iterateoperation, no copy is performed since chunks data are passed passed by reference.
- The type is limited to forbid copies of the builder instance.
First, instantiate the package for the element type (eg, String):
package String_Builder is new Util.Texts.Builders (Character, String);
Declare the string builder instance with its initial capacity:
Builder : String_Builder.Builder (256);
And append to it:
String_Builder.Append (Builder, "Hello");
To get the content collected in the builder instance, write a procedure that receives the chunk data as parameter:
procedure Collect (Item : in String) is ...
And use the
String_Builder.Iterate (Builder, Collect'Access);
Listeners package implements a simple observer/listener design pattern.
A subscriber registers to a list. When a change is made on an object, the
application can notify the subscribers which are then called with the object.
Creating the listener list
The listeners list contains a list of listener interfaces.
L : Util.Listeners.List;
The list is heterogeneous meaning that several kinds of listeners could be registered.
Creating the observers
Observers package must be instantiated with the type being
observed. In the example below, we will observe a string:
package String_Observers is new Util.Listeners.Observers (String);
Implementing the observer
Now we must implement the string observer:
type String_Observer is new String_Observer.Observer with null record; procedure Update (List : in String_Observer; Item : in String);
Registering the observer
An instance of the string observer must now be registered in the list.
O : aliased String_Observer; L.Append (O'Access);
Notifying the listeners is done by invoking the
provided by the
String_Observer.Notify (L, "Hello");
The Util.Events.Timers package provides a timer list that allows to have operations called on regular basis when a deadline has expired. It is very close to the Ada.Real_Time.Timing_Events package but it provides more flexibility by allowing to have several timer lists that run independently. Unlike the GNAT implementation, this timer list management does not use tasks at all. The timer list can therefore be used in a mono-task environment by the main process task. Furthermore you can control your own task priority by having your own task that uses the timer list.
The timer list is created by an instance of Timer_List:
Manager : Util.Events.Timers.Timer_List;
The timer list is protected against concurrent accesses so that timing events can be setup by a task but the timer handler is executed by another task.
A timer handler is defined by implementing the Timer interface with the Time_Handler procedure. A typical timer handler could be declared as follows:
type Timeout is new Timer with null record; overriding procedure Time_Handler (T : in out Timeout); My_Timeout : aliased Timeout;
The timer instance is represented by the Timer_Ref type that describes the handler to be called as well as the deadline time. The timer instance is initialized as follows:
T : Util.Events.Timers.Timer_Ref; Manager.Set_Timer (T, My_Timeout'Access, Ada.Real_Time.Seconds (1));
Timer Main Loop
Because the implementation does not impose any execution model, the timer management must be called regularly by some application's main loop. The Process procedure executes the timer handler that have elapsed and it returns the deadline to wait for the next timer to execute.
Deadline : Ada.Real_Time.Time; loop ... Manager.Process (Deadline); delay until Deadline; end loop;
Util.Executors generic package defines a queue of work that will be executed
by one or several tasks. The
Work_Type describes the type of the work and the
Execute procedure will be called by the task to execute the work. After instantiation
of the package, an instance of the
Executor_Manager is created with a number of desired
tasks. The tasks are then started by calling the
A work object is added to the executor's queue by using the
The work object is added in a concurrent fifo queue. One of the task managed by the
executor manager will pick the work object and run it.