!topic User-defined Task Attributes !key LSN-1034 User-defined Task Attributes !reference MS-G.5.2;4.8 !from Tucker Taft 92-09-22 !discussion Here is an attempt to design a "task attribute" package that provides for multiple attributes per task (up to some implementation-defined, potentially configurable, limit). with System; generic type Attribute_Type(<>) is limited private; package Task_Attribute is type Attribute_Ptr is access all Attribute_Type; procedure Set( Ptr : Attribute_Ptr; T : System.Task_Class := Current_Task); procedure Get( Ptr : out Attribute_Ptr; T : System.Task_Class := Current_Task); end Task_Attribute; Problems with the above: When task exits, how do we reclaim the storage? One way is to guarantee that if attribute is not null when task completes, it finalizes and then deallocates the object. Another is to call a user-defined operation that is called with the object and/or a pointer to it when the task completes. This operation does whatever it wants with the object. It can delete the object. If "object" is passed, freeing it sounds dicey. If pointer to object is passed, we don't dispatch, unless it is an access parameter, which can't be IN OUT. Another big concern is where the finalization occurs. Hmmmm. How about the following. A task must instantiate a package if it wants to have attributes. The TCB has one pointer to an object created by this instantiation. Here we go: package Task_Identification is generic package Allow_Task_Attributes is end; -- Instantiate this package to allow task attributes in task. -- Only attribs that have been assigned an index prior to -- this instantiation will be allowed? -- Or give it a parameter to say how many expected. type Attrib_Type is new System.Controlled with null; procedure Finalize(AT : in out Attrib_Type); -- Default finalize does nothing; override to indicate -- last wishes. procedure Release(AT : access Attrib_Type); -- Default release just calls unchecked_deallocation, which -- redispatches to Finalize and then reclaims storage; -- Override to decrement a reference count, etc., instead -- of immediately calling unchecked-dealloc. end Task_Identification; package body Task_Identification is type Attrib_Vector_Type(Num_Attribs : Attrib_Number) is new System.Controlled with record Attribs : Attrib_Ptr_Array(1..Num_Attribs); end record; procedure Initialize(AV : in out Attrib_Vector_Type) is begin Set_Task_Attrib(AV'UNCHECKED_ACCESS); end Initialize; procedure Finalize(AV : in out Attrib_Vector_Type) is begin for I in AV.Attribs'RANGE loop if AV.Attribs(I) /= null then Release(AV.Attribs(I)); -- dispatching on access type AV.Attribs(I) := null; end if; Set_Task_Attrib(null); end Finalize; Last_Attrib : Attrib_Number := 0; package body Allow_Task_Attributes is Attrib_Vector : Attrib_Vector_Type(Last_Attribs); -- On finalization, it sets task-attrib to null. begin Set_Task_Attrib(Attrib_Array'UNCHECKED_ACCESS); end Allow_Task_Attributes;