CVS difference for ai05s/ai05-0174-1.txt
--- ai05s/ai05-0174-1.txt 2010/02/25 05:01:43 1.4
+++ ai05s/ai05-0174-1.txt 2010/04/05 20:20:38 1.5
@@ -1,7 +1,7 @@
-!standard D.10.1 (00) 10-02-24 AI05-0174-1/02
-!standard 13.7(10)
-!standard 13.7(30)
+!standard D.10.1 (00) 10-04-05 AI05-0174-1/03
!class Amendment 09-10-23
+!status work item 10-03-13
+!status ARG Approved 9-0-2 10-02-26
!status work item 09-10-23
!status received 09-10-23
!priority High
@@ -40,9 +40,9 @@
We implement this functionality as an Ada package, a child of Ada:
package Ada.Synchronous_Barriers is
- pragma Pure;
+ pragma Pure(Synchronous_Barriers);
- subtype Barrier_Limit is Positive range 1 .. System.Max_Parallel_Release;
+ subtype Barrier_Limit is Positive range 1 .. <implementation-defined>;
type Synchronous_Barrier (Number_Waiting : Barrier_Limit) is limited private;
@@ -65,16 +65,6 @@
!wording
-Add after 13.7(10) (in package System):
-
- Max_Parallel_Release : constant := implementation-defined;
-
-Add after 13.7(30):
-
-Max_Parallel_Release
- The maximum number of tasks that can be released using an
- Ada.Synchronous_Barriers.Synchronous_Barrier object.
-
D.10.1 Barriers
This clause introduces a language-defined package to synchronously release a
@@ -85,11 +75,10 @@
The following language-defined library package exists:
-with System;
package Ada.Synchronous_Barriers is
- pragma Pure;
+ pragma Pure(Synchronous_Barriers);
- subtype Barrier_Limit is Positive range 1 .. System.Max_Parallel_Release;
+ subtype Barrier_Limit is Positive range 1 .. <implementation-defined>;
type Synchronous_Barrier (Number_Waiting : Barrier_Limit) is limited private;
@@ -116,6 +105,12 @@
task is unblocked and Program_Error is raised at the place of the call to
Wait_For_Release.
+It is implementation-defined whether an abnormal task which is waiting on a
+Synchronous_Barrier object is aborted immediately or aborted when the tasks
+waiting on the object are released.
+
+Wait_For_Release is a potentially blocking operation (see 9.5.1).
+
Bounded (Run-Time) Errors
It is a bounded error to call Wait_For_Release on a Synchronous_Barrier object
@@ -144,6 +139,13 @@
same task executes the sequential portion on different executions of a release
from a single barrier.
+We do not define when abort of a task which is waiting on a synchronous barrier
+takes effect, so long as it is no later than the release of the tasks on that
+barrier. We want this feature to be efficiently implementable using features of
+the target system (if it has appropriate operations). Since synchronous barriers
+cannot be safely used in the presence of abort (if too few tasks show up at a
+barrier, they will all be blocked forever), what happens is not important.
+
For the case of the protected object, we agreed on the following:
New syntax is required. Protected object semantics must be preserved and be
@@ -158,7 +160,7 @@
entry subprogram barrier condition. In a sequential version of the program, the
final task performs this action and does not need to wait.
-Another AI is needed to address this need. This AI is only focussed on the
+Another AI is needed to address this need. This AI is only focused on the
Synchronous_Barriers package.
!example
@@ -259,6 +261,876 @@
System.Max_Parallel_Release. I think it would be good (and easy) for an
implementation to document that constant. And in non-normative wording, it
doesn't really matter anyway.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Friday, March 12, 2010 4:47 PM
+
+A couple of further notes and questions regarding the Synchronous Barrier
+package that was discussed in Boston.
+
+I have come up with a couple of reference implementations for the package. (See
+the attached) The first implementation uses the POSIX calls for barriers (on a
+Linux desktop). The second implementation uses an Ada protected type to
+implement the package.
+
+The first thing I noted was that the package could not be Pure for the POSIX
+implementation, because the barrier type needs finalization. (So I changed
+pragma Pure to pragma Preelaborate)
+
+The Ada protected type implementation could be implemented with pragma Pure, but
+since the intent of this AI is to support the POSIX calls, we need to go to the
+lowest common denominator, pragma Preelaborate.
+
+Then it occurred to me that it could be quite useful to be able to use
+distributed barriers, as a RACW type.
+
+The barrier could be declared in a partition, and other partitions could call
+Wait_For_Release remotely.
+
+To support that capability, a pragma Remote_Types is needed in the package.
+Also, the Synchronous_Barrier type would need to be a tagged type, since a RACW
+type needs to designate a class wide type.
+
+It might be nice to declare;
+
+ type Distributed_Barrier is access all Synchronous_Barrier'Class;
+
+in the Synchronous_Barriers package as a convenience for those wishing to use
+barriers in a distributed manner. This also helps point out the possibility of
+distributed use for the package.
+
+Interestingly, this however rules out my implementation as a regular Ada
+protected type, because a tagged type cannot be completed by a protected type. I
+believe it should be possible to wrap the protected object as a component in a
+tagged type however.
+
+To summarize, my questions are;
+
+1) Should this package be a Remote_Types package?
+2) Should we declare Distributed_Barrier as a RACW type in the package?
+3) (Minor question) The parameter for Wait_For_Release is "The_Barrier".
+It strikes me as inconsistent to have "The_" as a preface to the parameter name.
+Do we do that anywhere else? I tried searching the RM for "The_", but it returns
+every occurrence of the word "the" in the RM. I am not sure I have the patience
+to check out all these occurrences to see if any are used as a preface on a
+parameter name. Should the parameter just be "Barrier" instead of "The_Barrier"?
+
+Finally, I did some timing tests to see the difference in execution times using
+the POSIX calls vs an Ada protected type.
+
+My test program calls a procedure using the barrier package a 100000 times.
+
+The time for the POSIX implementation came fairly consistently around
+4.8 seconds to execute, while the Ada implementation took typically around 5.3
+seconds to implement on my Linux desktop.
+
+This is a crude measurement, since it includes times needed for procedure calls,
+task initialization, etc, however it does show that the POSIX version is
+slightly faster.
+
+The tasks were essentially executing NOP's. I think that if each task had
+significant workloads to perform, then the time spent executing the barrier
+calls would fall into the noise level for either implementation.
+
+Regarding the reference implementations. Note that the POSIX implementation is a
+tagged type, while the Ada implementation is not tagged.
+
+---
+
+-- POSIX Barrier implementation
+
+private with Ada.Finalization;
+
+package Ada.Synchronous_Barriers is
+ pragma Preelaborate;
+ pragma Remote_Types;
+
+ subtype Barrier_Limit is Positive range 1 .. System.Max_Parallel_Release;
+
+ type Synchronous_Barrier
+ (Number_Waiting : Barrier_Limit) is tagged limited private;
+
+ procedure Wait_For_Release
+ (The_Barrier : in out Synchronous_Barrier;
+ Released_Last : out Boolean);
+
+ type Distributed_Barrier is access all Synchronous_Barrier'Class;
+
+private
+
+ use Interfaces;
+ use Ada.Finalization;
+
+ SIZEOF_PTHREAD_BARRIER_T : constant := 20;
+
+ type pthread_barrier_t_view is (size_based, align_based);
+ -- POSIX barriers data type.
+ type pthread_barrier_t (Kind : pthread_barrier_t_view := size_based) is
+ record
+ case Kind is
+ when size_based =>
+ size : C.char_array (1 .. SIZEOF_PTHREAD_BARRIER_T);
+ when align_based =>
+ align : C.long;
+ end case;
+ end record;
+
+ pragma Unchecked_Union (pthread_barrier_t);
+
+ type Synchronous_Barrier
+ (Number_Waiting : Barrier_Limit) is new Limited_Controlled with
+ record
+ POSIX_Barrier : aliased pthread_barrier_t;
+ end record;
+
+ overriding procedure Initialize (Barrier : in out Synchronous_Barrier);
+ overriding procedure Finalize (Barrier : in out Synchronous_Barrier);
+
+end Ada.Synchronous_Barriers;
+
+-- POSIX Implementation Body
+
+with System;
+package body Ada.Synchronous_Barriers is
+
+ EAGAIN : constant C.int := 11; -- Try again
+ EBUSY : constant C.int := 16; -- Device or resource Busy
+ EFAULT : constant C.int := 14; -- Bad address
+ EINVAL : constant C.int := 22; -- Invalid Argument
+ EOK : constant C.int := 0; -- Success
+
+ use type C.int;
+
+ PTHREAD_BARRIER_SERIAL_THREAD : constant C.int := -1;
+
+ function pthread_barrier_destroy
+ (barrier : not null access pthread_barrier_t) return C.int;
+
+ pragma Import
+ (Convention => C,
+ Entity => pthread_barrier_destroy,
+ External_Name => "pthread_barrier_destroy");
+
+ function pthread_barrier_init
+ (barrier : not null access pthread_barrier_t;
+ attr : System.Address := System.Null_Address;
+ count : C.unsigned) return C.int;
+
+ pragma Import
+ (Convention => C,
+ Entity => pthread_barrier_init,
+ External_Name => "pthread_barrier_init");
+
+ function pthread_barrier_wait
+ (barrier : not null access pthread_barrier_t) return C.int;
+
+ pragma Import
+ (Convention => C,
+ Entity => pthread_barrier_wait,
+ External_Name => "pthread_barrier_wait");
+
+ overriding procedure Finalize (Barrier : in out Synchronous_Barrier) is
+ begin
+ case pthread_barrier_destroy
+ (barrier => Barrier.POSIX_Barrier'Access) is
+
+ when EOK =>
+ -- Success.
+ null;
+
+ when EBUSY =>
+ -- The barrier is in use.
+ raise Program_Error with "Barrier in use";
+
+ when EINVAL =>
+ -- Invalid Barrier
+ raise Program_Error with "Invalid Barrier";
+
+ when others =>
+ raise Program_Error with "Unexpected return code";
+
+ end case;
+
+ end Finalize;
+
+ overriding procedure Initialize (Barrier : in out Synchronous_Barrier) is
+ begin
+ case pthread_barrier_init
+ (barrier => Barrier.POSIX_Barrier'Access,
+ attr => System.Null_Address,
+ count => C.unsigned (Barrier.Number_Waiting)) is
+
+ when EOK =>
+ -- Success.
+ null;
+
+ when EAGAIN =>
+ -- The system lacks the necessary resources to
+ -- initialize another barrier.
+ raise Storage_Error;
+
+ when EBUSY =>
+ -- Attempt to reinitialize a barrier while it's in use.
+ raise Program_Error with "Barrier in Use";
+
+ when EFAULT =>
+ -- A fault occurred when the kernel tried to
+ -- access barrier or attr.
+ raise Program_Error with "Kernel Fault";
+
+ when EINVAL =>
+ -- Invalid value specified by attr.
+ raise Program_Error with "Invalid attr Argument";
+
+ when others =>
+ raise Program_Error with "Unexpected return code";
+
+ end case;
+
+ end Initialize;
+
+ ----------------------
+ -- Wait_For_Release --
+ ----------------------
+
+ procedure Wait_For_Release
+ (The_Barrier : in out Synchronous_Barrier;
+ Released_Last : out Boolean)
+ is
+ Result : C.int;
+ begin
+ Result := pthread_barrier_wait
+ (barrier => The_Barrier.POSIX_Barrier'Access);
+
+ case Result is
+
+ when EINVAL =>
+ -- Invalid value specified by attr.
+ raise Program_Error with "Barrier isn't initialized";
+
+ when others =>
+ Released_Last := (Result = PTHREAD_BARRIER_SERIAL_THREAD);
+ end case;
+ end Wait_For_Release;
+
+end Ada.Synchronous_Barriers;
+
+-------------------------------------------------------------------------------
+
+-- Ada Protected Type implementation
+
+with System;
+
+package Ada.Synchronous_Barriers is
+ pragma Preelaborate;
+ pragma Remote_Types;
+
+ package System renames brSystem;
+
+ subtype Barrier_Limit is Positive range 1 .. System.Max_Parallel_Release;
+
+ type Synchronous_Barrier
+ (Number_Waiting : Barrier_Limit) is limited private;
+
+ procedure Wait_For_Release
+ (The_Barrier : in out Synchronous_Barrier;
+ Released_Last : out Boolean);
+
+ type Distributed_Barrier is access all Synchronous_Barrier'Class;
+
+private
+
+ protected type Synchronous_Barrier (Number_Waiting : Barrier_Limit) is
+ entry Wait_For_All_Tasks_To_Block (Released_Last : out Boolean);
+ private
+ Done : Boolean := False;
+ end Synchronous_Barrier;
+
+end Ada.Synchronous_Barriers;
+
+package body Ada.Synchronous_Barriers is
+
+ ----------------------
+ -- Wait_For_Release --
+ ----------------------
+
+ procedure Wait_For_Release
+ (The_Barrier : in out Synchronous_Barrier;
+ Released_Last : out Boolean)
+ is
+ begin
+ The_Barrier.Wait_For_All_Tasks_To_Block (Released_Last);
+ end Wait_For_Release;
+
+ protected body Synchronous_Barrier is
+
+ ---------------------------------
+ -- Wait_For_All_Tasks_To_Block --
+ ---------------------------------
+
+ entry Wait_For_All_Tasks_To_Block
+ (Released_Last : out Boolean)
+ when Wait_For_All_Tasks_To_Block'Count = Number_Waiting or Done is
+ begin
+ Done := True;
+ if Wait_For_All_Tasks_To_Block'Count = 0 then
+ Released_Last := True;
+ Done := False;
+ else
+ Released_Last := False;
+ end if;
+ end Wait_For_All_Tasks_To_Block;
+
+ end Synchronous_Barrier;
+
+end Ada.Synchronous_Barriers;
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, March 13, 2010 12:05 AM
+
+> A couple of further notes and questions regarding the Synchronous
+> Barrier package that was discussed in Boston.
+
+We already approved this AI at the last meeting. Are you asking to reopen it,
+create a second AI, or something else??
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, March 13, 2010 12:25 AM
+
+Now for the technical response:
+
+> It might be nice to declare;
+>
+> type Distributed_Barrier is access all Synchronous_Barrier'Class;
+>
+> in the Synchronous_Barriers package as a convenience for those wishing
+> to use barriers in a distributed manner. This also helps point out the
+> possibility of distributed use for the package.
+
+I *detest* sticking random types and objects into packages because "they might
+be convenient for someone". Especially when said types have nothing to do with
+the operations in the package. These things turn into maintenance hazards down
+the road.
+
+<Rant> After all, the reason that we can't make Unbounded_Strings Remote_Types
+is that someone thought that sticking a random access-to-string type into the
+package would be "convenient". That's despite the fact that the about the only
+time you could be sure that you wouldn't want to use such a type is when you are
+using real Unbounded_Strings! And if you *aren't* using Unbounded_Strings, why
+would you want to drag a lot of finalization stuff into your program?? Just
+friggin' stupid. Grumble. </Rant>
+
+Anyway, let's not repeat that silliness. If someone needs an RACW type, let them
+declare it.
+
+> To summarize, my questions are;
+>
+> 1) Should this package be a Remote_Types package?
+
+This I can't answer. The original version is Pure, so it would work that way. If
+we change it to Preelaborate, Remote_Types tends to go along as much as
+possible. But I can't say if there is an implementation burden (say on a 'real'
+multiprocessor with separate CPUs).
+
+> 2) Should we declare Distributed_Barrier as a RACW type in the
+> package?
+
+No. See above.
+
+> 3) (Minor question) The parameter for Wait_For_Release is "The_Barrier".
+> It strikes me as inconsistent to have "The_" as a preface to the
+> parameter name. Do we do that anywhere else? I tried searching the RM
+> for "The_", but it returns every occurrence of the word "the" in the
+> RM.
+
+I solved this problem by searching the Bob Duff special text-only version of the
+RM (an ancient one, I haven't regenerated it in forever) with a most complex
+tool, the command-line Find utility that come built-in to Windows (an MS-DOS
+holdover). ;-)
+
+There appears to be exactly one such parameter, The_Tag found in
+Ada.Tags.Generic_Dispatching_Constructor (3.9(18.2/2)). So it surely isn't
+common, but there is precedent (and even in something I wrote, although I would
+have said I never use parameters named like that -- so go figure).
+
+Whether that is enough to leave or change the naming I can't say.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Saturday, March 13, 2010 8:22 AM
+
+...
+> <Rant> After all, the reason that we can't make Unbounded_Strings
+> Remote_Types is that someone thought that sticking a random
+> access-to-string type into the package would be "convenient". That's
+> despite the fact that the about the only time you could be sure that
+> you wouldn't want to use such a type is when you are using real
+> Unbounded_Strings! And if you *aren't* using Unbounded_Strings, why
+> would you want to drag a lot of finalization stuff into your program??
+> Just friggin' stupid. Grumble. </Rant>
+
+I agree that putting Accrss_String was a bad idea for Unbounded_Strings, but NOT
+having a standard Access_String type *somewhere* is an error that is even worse!
+The result is a proliferation of incompatible string access types around a
+program or system
+
+> Anyway, let's not repeat that silliness. If someone needs an RACW
+> type, let them declare it.
+
+Not clear to me that the analogy is right here, that type looks like an
+advantageous addition to me, I don't agree with dismissing it as "silliness".
+
+>> To summarize, my questions are;
+>>
+>> 1) Should this package be a Remote_Types package?
+>
+> This I can't answer. The original version is Pure, so it would work
+> that way. If we change it to Preelaborate, Remote_Types tends to go
+> along as much as possible. But I can't say if there is an
+> implementation burden (say on a 'real' multiprocessor with separate CPUs).
+
+How can there be an implementation burden, no one says you have to implement
+this in pure Ada (surely you don't think the finalization package is implemented
+in pure Ada :-))
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Saturday, March 13, 2010 4:00 PM
+
+Thanks for doing some trial implementations.
+I agree that we don't normally start parameter names with "The_". The most
+interesting thing for me was that the "pure" Ada implementation was very nearly
+as fast as the Posix implementation. That means to me that protected objects are
+pretty flexible, if they can nearly match the performance of a special purpose
+O/S feature.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Saturday, March 13, 2010 4:53 PM
+
+> The time for the POSIX implementation came fairly consistently around
+> 4.8 seconds to execute, while the Ada implementation took typically
+> around 5.3 seconds to implement on my Linux desktop.
+ ^^^^^^^^^
+Wow, that's impressive! How long did it take to execute?
+
+;-) ;-)
+
+****************************************************************
+
+From: Brad Moore
+Sent: Sunday, March 14, 2010 1:14 AM
+
+I don't usually like to mince words, however I am happy to put that particular
+instance of that word in the shredder. It passed my spell-checker, and my
+grammar checker. If only I had a semantics-checker. :)
+
+****************************************************************
+
+From: Brad Moore
+Sent: Saturday, March 13, 2010 9:11 PM
+
+> We already approved this AI at the last meeting. Are you asking to
+> reopen it, create a second AI, or something else??
+
+Whichever makes the most sense. Though to me, the most sense would be to reopen
+the AI.
+
+The pragma Pure is a problem with the current version of the AI, since it seems
+to rule out the Ada implementation that utilizes the POSIX barrier calls. That
+suggests reopening the existing AI. Perhaps the package could be a non-Ada
+implementation, but it seems a shame to not be able to implement the package in
+Ada.
+
+On the other hand, I could see the distributed barrier feature as a new AI,
+since it involves a new capability. But since that would require making the
+Synchronous_Barrier type a tagged type, I wouldn't want to see AI 174 go
+through, and then try to address the second AI as a post amendment AI, because
+that would involve a backwards incompatibility. If we think distributed barriers
+could be useful, we should try to fix it now while we have the chance to make
+the change without introducing any incompatibilities. Because a new AI would be
+so tightly coupled with AI 174 anyway, we might as well address all this under
+the existing AI, IMHO.
+
+It's unfortunate that the pragma Pure issue wasn't caught before Boston, though
+I do recall a question was raised on whether the package could be pure or not.
+At the time, nobody came up with a reason why it couldn't be Pure. It's one of
+those things that one might not detect until one actually tries to implement the
+package.
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Sunday, March 14, 2010 5:08 AM
+
+> The pragma Pure is a problem with the current version of the AI, since
+> it seems to rule out the Ada implementation that utilizes the POSIX
+> barrier calls. That suggests reopening the existing AI.
+> Perhaps the package could be a non-Ada implementation, but it seems a
+> shame to not be able to implement the package in Ada.
+
+with GNAT, we disable the categorization checks throughout the run-time, (more
+accurately we make them warnings, and then supress the warning where needed) and
+this suppression is required in several situations, so we would not find it a
+problem at all.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Sunday, March 14, 2010 1:02 PM
+
+Hmmm, maybe the package should stay Pure then, since it can be implemented in
+Ada with a Protected Type (using pragma Pure), and the protected type version
+performs comparably to the POSIX barrier implementation. If a compiler vendor
+wishes to use the POSIX calls, they can still do so.
+
+Regarding the changed to a tagged type. I think this is still worth considering,
+since it allows for distributed usage.
+
+However, if we declare the Distributed_Barrier access type in a pure package,
+then the Storage_Size for the type needs to be specified as 0.
+
+That seems to not be a problem though, since an instance of a RACW type is never
+allocated. (I think).
+
+There is one other consideration though.
+
+The POSIX call to initialize the barrier has a parameter to specify attributes
+of the barrier.
+
+ function pthread_barrier_init
+ (barrier : not null access pthread_barrier_t;
+ attr : System.Address := System.Null_Address;
+ count : C.unsigned) return C.int;
+
+If attr is NULL, the default barrier attributes are used; the effect is the same
+as passing the address of a default barrier attributes object. In my reference
+implementations, I use these default barrier attributes.
+
+Currently, only the process-shared attribute is provided in POSIX, and the
+pthread_barrierattr_getpshared() and pthread_barrierattr_setpshared() C
+functions are used to get and set the attribute.
+
+The process-shared attribute can have the following values:
+
+PTHREAD_PROCESS_PRIVATE
+
+ The barrier can only be operated upon by threads created within the same
+ process as the thread that initialized the barrier. This is the default
+ value of the process-shared attribute.
+
+PTHREAD_PROCESS_SHARED
+
+ The barrier can be operated upon by any thread that has access to the memory
+ where the barrier is allocated.
+
+The Ada package interface as currently defined does not provide a way to control
+this attribute.
+
+By having the Distributed_Barrier type though, we effectively get this
+capability and more since the barrier is not only available to other partitions
+on the same computer, they can be accessed by remote computers, if the compiler
+implementation supports the distributed annex.
+
+I wonder though whether we should be providing a way to specify barrier
+attributes in the synchronous barrier package as some sort of system defined set
+of attributes. An implementation that uses a protected type instead of the POSIX
+calls might only provide the default attribute (equivalent to
+PTHREAD_PROCESS_PRIVATE).
+
+On another note,
+I have attached a third implementation of the Synchronous_Barriers package that
+implements the barrier as a tagged type that contains a protected object
+component.
+
+I ran the same timing tests, and found it interesting to note that this Ada
+implementation shaves a tenth of a second off the original Ada implementation. I
+cannot offer an explanation for why this version is faster over the first one. I
+would have expected it to be slightly slower if anything, since the protected
+type is wrapped inside a tagged type.
+
+i.e. Original Ada => 5.30 - 5.36 seconds
+ New Ada => 5.23 - 5.26 seconds
+ POSIX => 4.94 - 4.97 seconds
+
+---
+
+with System;
+
+package Ada.Synchronous_Barriers is
+ pragma Pure;
+
+ subtype Barrier_Limit is Positive range 1 .. System.Max_Parallel_Release;
+
+ type Synchronous_Barrier
+ (Number_Waiting : Barrier_Limit) is tagged limited private;
+
+ procedure Wait_For_Release
+ (Barrier : in out Synchronous_Barrier;
+ Released_Last : out Boolean);
+
+ type Distributed_Barrier is access all Synchronous_Barrier'Class;
+
+private
+
+ for Distributed_Barrier'Storage_Size use 0;
+
+ protected type Barrier_Type (Number_Waiting : Barrier_Limit) is
+ entry Wait_For_All_Tasks_To_Block (Released_Last : out Boolean);
+ private
+ Done : Boolean := False;
+ end Barrier_Type;
+
+ type Synchronous_Barrier
+ (Number_Waiting : Barrier_Limit) is tagged limited
+ record
+ The_Barrier : Barrier_Type (Number_Waiting);
+ end record;
+
+end Ada.Synchronous_Barriers;
+
+package body Ada.Synchronous_Barriers is
+
+ ----------------------
+ -- Wait_For_Release --
+ ----------------------
+
+ procedure Wait_For_Release
+ (Barrier : in out Synchronous_Barrier;
+ Released_Last : out Boolean)
+ is
+ begin
+ Barrier.The_Barrier.Wait_For_All_Tasks_To_Block (Released_Last);
+ end Wait_For_Release;
+
+ protected body Barrier_Type is
+
+ ---------------------------------
+ -- Wait_For_All_Tasks_To_Block --
+ ---------------------------------
+
+ entry Wait_For_All_Tasks_To_Block
+ (Released_Last : out Boolean)
+ when Wait_For_All_Tasks_To_Block'Count = Number_Waiting or Done is
+ begin
+ Done := True;
+ if Wait_For_All_Tasks_To_Block'Count = 0 then
+ Released_Last := True;
+ Done := False;
+ else
+ Released_Last := False;
+ end if;
+ end Wait_For_All_Tasks_To_Block;
+
+ end Barrier_Type;
+
+end Ada.Synchronous_Barriers;
+
+****************************************************************
+
+From: Bob Duff
+Sent: Sunday, March 14, 2010 1:43 PM
+
+> I wonder though whether we should be providing a way to specify
+> barrier attributes in the synchronous barrier package as some sort of
+> system defined set of attributes. An implementation that uses a
+> protected type instead of the POSIX calls might only provide the
+> default attribute (equivalent to PTHREAD_PROCESS_PRIVATE).
+
+Seems better to keep it portable. If implementations want to provide
+implementation dependent bells and whistles they can do so (e.g. put additional
+operations in a child package).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Sunday, March 14, 2010 2:44 PM
+
+I would vote for making it Preelaborate.
+It seems likely that this package should be implementable without special
+treatment by the compiler, and it seems pretty natural to use finalization.
+
+I think we want to make it a Remote_Types package so that it *can* be used with
+a RACW type, but not actually declare such a type inside it. That does leave
+open the question of whether it should be declared as a visibly tagged type, or
+let the user wanting to use it with an RACW to wrap it in a tagged type. I would
+probably let the user wrap it, since the whole idea of distributed barriers
+seems a bit unlikely to me, given how easily a barrier will freeze up if even a
+single task fails to "show up."
+
+****************************************************************
+
+From: Brad Moore
+Sent: Sunday, March 14, 2010 11:14 PM
+
+> I would vote for making it Preelaborate.
+> It seems likely that this package should be implementable without
+> special treatment by the compiler, and it seems pretty natural to use
+> finalization.
+
+I could go either way, but I think it would be preferable to use Preelaborate
+for the same reasons you mention.
+
+> I think we want to make it a Remote_Types package so that it *can* be
+> used with a RACW type, but not actually declare such a type inside it.
+> That does leave open the question of whether it should be declared as
+> a visibly tagged type, or let the user wanting to use it with an RACW
+> to wrap it in a tagged type.
+> I would probably let the user wrap it, since the whole idea of
+> distributed barriers seems a bit unlikely to me, given how easily a
+> barrier will freeze up if even a single task fails to "show up."
+
+Good points. Do you think there is any likelihood that users might want to
+extend the type for other reasons than remote usage? Perhaps to include state
+information to assist the final "cleanup" task that gets the "Released_Last" out
+parameter set to true? I suppose you could argue that the user could just as
+easily wrap the type in a tagged type for that purpose. If it seems that this
+would be fairly common usage though, then having a tagged type would be more
+convenient. If that scenario seems unlikely, then leaving it as untagged could
+make more sense.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Sunday, March 14, 2010 11:04 PM
+
+Hi Jon,
+ I am forwarding this to the ARG mailing list.
+Hopefully Brad will see it.
+
+Jon S. Squire. wrote:
+> Please send a test case.
+>
+> I tried to write a test for both versions, no luck.
+> Could not get them to compile.
+>
+> I have used barriers with both Java and Python.
+> I really need them for Ada.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Monday, March 15, 2010 12:05 AM
+
+You probably had problems getting the implementations to compile because the
+System package currently does not define Max_Parallel_Release constant. That
+does not exist yet, until AI05-174 becomes official, as proposed for the Ada
+2012 amendment. Actually, I recall there was some change related to that
+constant, but I will need to see the minutes of the Boston ARG meeting (which
+haven't been prepared yet) to see what was decided upon.
+
+[The rest of the message describes a sample implementation, complete with
+compilation instructions. It's too large to include here. Contact
+Brad or the ARG Editor to get a copy.]
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, March 15, 2010 7:30 AM
+
+I believe we decided to eliminate Max_Parallel_Release from System. It is too
+specialized a value to appear there. There seems no reason not to put it
+directly in the new package. In fact I think we decided to eliminate it
+completely, by simply saying the index high bound was an implementation-defined
+value, which you could always determine using the 'Last attribute.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Monday, March 15, 2010 10:43 AM
+
+My recollection is that I suggested that, but you said it was a stupid idea
+(well, you were more polite than that ;-)), because the 'Last is intended to be
+something like 2**31-1, whereas Max_Parallel_Release might be much smaller. So
+I thought we ended up agreeing to keep Max_Parallel_Release, but move it into
+this package (instead of System).
+
+But we'll have to look at Randy's minutes to be sure.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 15, 2010 12:43 PM
+
+My notes reflect what Tucker said (get rid of it completely and just use 'Last). I don't have any of your "recollections". You may have had a stupid idea during the meeting :-), but I don't think this was it.
+
+Specifically, my notes (which need some fleshing out) have:
+
+ subtype Barrier_Limit is Positive range 1 .. <<implementation-defined>>;
+
+ Users can use Barrier_Limit'Last.
+
+ Get rid of the System change and with of System.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Monday, March 15, 2010 4:56 PM
+
+> My notes reflect what Tucker said (get rid of it completely and just
+> use 'Last). I don't have any of your "recollections".
+
+Your notes should be trusted far more than my vague memory.
+
+>... You may have had a stupid
+> idea during the meeting :-), ...
+
+Well, I'm pretty sure I at least made some silly jokes.
+
+>...but I don't think this was it.
+>
+> Specifically, my notes (which need some fleshing out) have:
+>
+> subtype Barrier_Limit is Positive range 1 .. <<implementation-defined>>;
+>
+> Users can use Barrier_Limit'Last.
+>
+> Get rid of the System change and with of System.
+
+Thanks for taking good notes! I know it's hard, especially when you're also
+trying to participate in the discussion.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, March 15, 2010 5:07 PM
+
+Actually, I vaguely remember the same thing that Bob vaguely remembered. But
+perhaps we went back and forth a couple of times, and you only recorded the
+final decision.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 15, 2010 5:42 PM
+
+Or maybe I simply never heard that part of the discussion because I was too busy
+recording the first part. (It happens.) I definitely don't recall any discussion
+about *not* making the value 'Last -- and I can't think of any advantage to
+having a separate constant for barriers (this value reflects a target OS - or
+implementation - limit, so it isn't going to change often).
+
+Maybe you are thinking about the similar value for CPUs, which is likely to be
+determined at runtime by the target hardware. There, a separate function to get
+the limit makes sense, with a larger value for 'Last for the largest number of
+CPUs that the target OS supports.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, March 15, 2010 7:26 PM
+
+I think you might be right that I was confusing the number of CPUs and the
+barrier limit.
****************************************************************
Questions? Ask the ACAA Technical Agent