From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: backlog3.nntp.ams.giganews.com!border1.nntp.ams.giganews.com!nntp.giganews.com!eternal-september.org!feeder.eternal-september.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: STM32F4 Discovery, communication and libraries Date: Sun, 31 Aug 2014 21:41:15 +0300 Organization: Tidorum Ltd Message-ID: References: <60a42dc6-d8d0-4432-ae5a-86de18b82840@googlegroups.com> <5kkrv9hejn2qhdckkeo8lidkbh3bkme1gn@4ax.com> <5b91313c-acf9-4a6e-b157-6ba7c8021567@googlegroups.com> <0513ad07-6fbe-463a-be6f-097cd5113f52@googlegroups.com> <4f1ec65a-d66a-40bf-a0d6-278fde206e70@googlegroups.com> <1cjwzr30b24xy.11kpydntxhfo5$.dlg@40tude.net> <1xrcksk78afho$.xz6vgakq9o4t.dlg@40tude.net> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: individual.net 72vAxzvsw4ejGkpjTN7iXgsppNabC5D4UiErR/PNFbNL/FF/5M Cancel-Lock: sha1:UQd2Ra7W7aXRxUhsu2QapftT8dQ= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 In-Reply-To: <1xrcksk78afho$.xz6vgakq9o4t.dlg@40tude.net> Date: 2014-08-31T21:41:15+03:00 List-Id: On 14-08-31 10:02 , Dmitry A. Kazakov wrote: > On Fri, 29 Aug 2014 19:31:00 +0300, Niklas Holsti wrote: > >> For example (from memory, not tested): > > [...] > >> Did that answer your question? > > Sort of. Good. > No_Local_Protected_Objects means all requests are pre-allocated at the > library level and distributed by another protected object? With busy > waiting for a free request? No, the _request_ in my example code is not a protected object; it is an ordinary record type. It _refers_ to a protected object which is a kind of "I/O wait object". The PO "wait object" is of course statically allocated (by Ravenscar rules). Any task that will issue I/O requests must allocate such a PO for itself. (If the task uses several different I/O servers, which have different "wait object" types, the task has to allocate one PO for each such I/O server it will use.) (Oh well, of course one could also statically allocate a shared pool of such POs and use some kind of protocol by which tasks can reserve a PO from the pool when they need one, but why make things difficult?) The example code I gave assumed that each client issues at most one request at a time, to one server, and then waits for the request to be completed. This requires one request object (which can be locally allocated, or can even have value-semantics and be constructed in the I/O call as in my example code), and one PO, which can be reused for any number of requests. By adding request identifiers and other data-structure complexities one can implement multiple concurrent requests, waiting for any one of multiple requests to complete ("select"), etc. > When I evaluated Ravenscar for our middleware (long ago), the concern was > publisher/subscriber services. I/O queue viewed as one of them. I didn't > consider a solution like yours because the requirement was that more than > one task could await for same I/O event. You reserve the event for single > task and other publisher/subscriber services (e.g. the data logger, network > data server, health monitor etc) may not use it because of > Max_Protected_Entries = 1. The event cannot propagate because of > No_Requeue_Statements. Tasks could flood the queue with their > requests/events but they cannot do that for more than one queue. You list a lot of things there... I don't really see how they are related to each other, or if they are separate problems. If for some reason you want to wake up two tasks when one I/O finishes, the sample principle can be used: record two references, to two protected objects - one per task - in the I/O request, and signal both of them when the I/O completes. For publish/subscribe, I would do something like this (not tested): protected type Mailbox_T -- -- Each subscriber has an object of this type. -- is procedure Signal (Event : in Event_Data_T); -- Called by the Publisher (through Publication_Channel, see -- below) to broadcast the Event to each subscriber. procedure Get_Last ( Signalled : out Boolean; Event : out Event_Data_T); -- Called by the Subscriber to poll (ask) if a new -- Event has been Signalled (i.e. non-blocking). entry Await (Event : out Event_Data_T); -- Called by the Subscriber when it wants to wait for -- the next broadcast Event. ... end Mailbox_T; type Mailbox_Ref is access all Mailbox_T; -- What the Publisher knows about a Subscriber. protected Publication_Channel is procedure Subscribe ( Mailbox : in Mailbox_Ref; Success : out Boolean); -- Called by a new Subcriber. -- Enters the Mailbox (reference) in the subscriber list, or -- fails if the list is full (Success returned as False). procedure Publish (Event : in Event_Data_T); -- Called by the Publisher to broadcast a new Event -- to all subscribers in the list, by calling the Signal -- operation of the Mailbox for each subscriber. private Subscribers : array (1 .. 100) of Mailbox_Ref; Num_Subscribers : Natural := 0; -- The active subscriptions are indexed 1 .. Num_Subscribers. end Publication_Channel; Depending on the timing and on whether it is important not to lose any events, Mailbox_T may need an internal Event queue, or there may be a global queue of past events to which the queue in Mailbox_T holds references, and other such data structure refinements, all orthogonal to Ravenscar constraints. > It might do what you wanted, but it does not look scalable for the OP's > purpose. So far, I don't see anything in the OP's requirements that could not be implemented with Ravenscar tasking. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .