File: gnatcoll-pools.ads

package info (click to toggle)
libgnatcoll 18-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 5,068 kB
  • sloc: ada: 40,393; python: 354; ansic: 310; makefile: 245; sh: 31
file content (189 lines) | stat: -rw-r--r-- 9,050 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
------------------------------------------------------------------------------
--                             M O D E L I N G                              --
--                                                                          --
--                     Copyright (C) 2010-2017, AdaCore                     --
--                                                                          --
-- This library is free software;  you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your  option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
------------------------------------------------------------------------------

--  This package implements resource pools.
--  The resources are created once (the first time they are needed). The
--  application can then get a temporary exclusive handle on a resource (ie if
--  another part of the application is also requesting a resource, it will in
--  fact retrieve another instance). When the resource is no longer used by the
--  application, it is automatically released into the pool, and will be reused
--  the next time the application requests a resource.
--
--  A typical usage is when the resource creation is expensive, such as a pool
--  of database connections.
--
--  Each instantiation of this package provides one task-safe global pool.
--  However, this pool can contains multiple sets of elements. Each sets has
--  its own factory parameter. The subprograms will by default apply to the
--  first such subset, since in most cases you will only need one such subset
--  in your application. An example where multiple subsets might be needed is
--  for instance when we have a pool of database connections. We would for
--  instance one subset for each DBMS we want to connect to it. Each subset
--  then contains a number of connections to that specific DBMS.
--  Of course, this pattern could be implemented by having multiple
--  instantiations of GNATCOLL.Pools, but this makes the API more complex and
--  forces the duplication of the whole GNATCOLL.SQL.Session API.

pragma Ada_2012;

private with GNATCOLL.Refcount;

generic
   type Element_Type is private;
   --  The elements that are pooled

   type Factory_Param is private;
   with function Factory (Param : Factory_Param) return Element_Type;
   --  Information needed to create new elements as needed. This is passed as
   --  is to the Factory function.

   type Resource_Set is (<>);
   --  Represents a set of elements within the pool.
   --  There can be multiple such sets in one pool. Each set is associated with
   --  its own factory parameter, but all other elements are compatible between
   --  the various sets (in particular, the resources are the same, so the rest
   --  of the application doesn't need to know which set this resource is
   --  from).
   --  Most times, a pool will need only one such subset, which is created by
   --  default. All subprograms below apply to this default set, unless
   --  otherwise specified.

   with procedure Free (Self : in out Element_Type) is null;
   --  Called when the [Self] is finally removed from the pool

   with procedure On_Release (Self : in out Element_Type) is null;
   --  Called when Self is released into the pool.
   --  The application has no more reference to that element, apart from the
   --  one in the pool.
   --  The result of Element.Element should not be freed yet, since it is
   --  returned to the pool (instead, override the formal [Free] parameter).
   --  But any other custom field from Element should be reset at that time.

   with procedure Free_Param (Data : in out Factory_Param) is null;
   --  Free Factory_Param.
   --  Called when the pool itself is freed.

package GNATCOLL.Pools is

   Default_Set : constant Resource_Set;

   type Resource is tagged private;
   No_Resource : constant Resource;
   --  A resource retrieved from the pool.
   --  This is a smart pointer to an Element_Type. When your application has no
   --  more references to it, the Element_Type is released into the pool (not
   --  destroyed).
   --  The resource itself does its refcounting in a task-safe manner.

   function Element (Self : Resource) return access Element_Type;
   --  Get a copy of the element stored in the wrapper. The result should
   --  really only be used while you have a handle on Self, so that you are
   --  sure it has not been released into the pool, and thus reset.

   type Weak_Resource is private;
   Null_Weak_Resource : constant Weak_Resource;
   function Get_Weak (Self : Resource'Class) return Weak_Resource;
   procedure Get (Self : Weak_Resource; Res : out Resource);
   --  A resource with a weak-reference.
   --  Such a resource does not prevent the release into the pool when no other
   --  Resource exists. While the resource has not been released, you can get
   --  access to it through this Weak_Resource. One it has been released, the
   --  Weak_Resource will return No_Resource.
   --  This datatype can thus be stored in some long-lived data structure, if
   --  you do not want to prevent the release. For instance if you have a
   --  cache of some sort.

   function Was_Freed (Self : Weak_Resource) return Boolean;
   --  Whether the resource monitored by Self was released.

   procedure Set_Factory
     (Param        : Factory_Param;
      Max_Elements : Positive;
      Set          : Resource_Set := Default_Set);
   --  Configure the internal resource pool. This must be called before
   --  calling Get, and only once.

   procedure Get
     (Self : out Resource'Class;
      Set  : Resource_Set := Default_Set);
   --  Return an available resource (or create a new one if the pool is not
   --  full yet and none is available).
   --  In a multitasking context, this blocks until a resource is actually
   --  available.
   --  The resource is automatically released when you no longer have a
   --  reference to the wrapper.

   procedure Free;
   --  Detach all resources from the pool.
   --  Any resource that is not in use elsewhere (ie retrieved by Get) will
   --  get freed (and the corresponding [Free] formal subprogram will be
   --  called).

   function Get_Refcount (Self : Resource) return Natural;
   --  Return the reference counting for self

   function Get_Factory_Param
     (Set : Resource_Set := Default_Set) return access Factory_Param;
   --  Returns a the factory param used for the set.
   --  Remember that the factory will not be called again for resources that
   --  have already been created, even if they have been released to the pool
   --  since then.
   --  This must only be called when you have called Set_Factory for the
   --  corresponding set.
   --  The returned value is shared among multiple threads, so you should only
   --  modify it from a protected region or before tasks are created.

private

   type Pool_Resource is record
      Element           : aliased Element_Type;
      Available         : Boolean;  --  Is the resource available ?
   end record;
   type Pool_Resource_Access is access all Pool_Resource;
   --  The data stored in the pool.
   --  These are not smart pointers, which are created on demand in Get.

   Default_Set : constant Resource_Set := Resource_Set'First;

   type Resource_Data is record
      In_Set : Pool_Resource_Access;
      Set    : Resource_Set;
   end record;
   procedure Free (Self : in out Resource_Data);
   package Pointers is new GNATCOLL.Refcount.Shared_Pointers
     (Resource_Data, Free);
   --  The smart pointers returned to the application. When no longer
   --  referenced, the resource is released back into the pool.

   type Weak_Resource is record
      Ref : Pointers.Weak_Ref;
   end record;

   type Resource is new Pointers.Ref with null record;
   No_Resource : constant Resource :=
     Resource'(Pointers.Null_Ref with null record);

   Null_Weak_Resource : constant Weak_Resource :=
     (Ref => Pointers.Null_Weak_Ref);

end GNATCOLL.Pools;