-------------------------------------------------------------- Suggested re-wording for section 5.3.3.6 g() If g is NULL, the SCE-MI checks for pending input or output message transfers to be performed and dispatches them, returning immediately afterwards. If g() is non-NULL, the SCE-MI enters a loop of performing input or output message transfers but calling g() only for each output message. For purposes of discussions of the g() function in this section, "output message" is considered to be one of the following: o An arriving message in a SCE-MI message output port that will result in a receive callback being called. o An input ready notification that will result in an input ready callback being called. > While this text is really clear to me, I worry that overloading > the term `output message' is going to cause confusion, especially > when people go back some time later and only read the g() > examples. Perhaps we should define a special term for this, such > as `service request'. We can define service request using your > words: > > A service request is defined to be one of the following: > > o An arriving message in a SCE-MI message output port that will result > in a receive callback being called. > o An input ready notification that will result in an input ready > callback being called. > > Then replace `output message' with `service request' in your > proposed text. >> johnS: >> It seems reasonable to replace 'output message' with the more >> general term 'service request' as you've suggested while leaving >> the remainder of the re-wording I proposed the same. When g() returns 0, control returns from the loop. When g() is called, an indication of whether there is at least one output message pending is made with the pending flag. The context argument to g() is the pointer which is passed as the context argument to ::ServiceLoop(). -------------------------------------------------------------- Suggested re-wording for section 5.3.3.6.1 Some applications force a return from the ::ServiceLoop() call after processing each output message. The ::ServiceLoop() call always guarantees a separate call is made to the g() function for each output message processed. In fact, it is possible to force ::ServiceLoop() to return back to the application once per output message by having the g() function return a 0. So even if all g() does is return 0, as follows, int g( void */*context*/, bool /*pending*/ ){ return 0; } the application forces a return from ::ServiceLoop() for each processed output message. NOTE: In this case, the ::ServiceLoop() does not block because it also returns even if no output message was found (i.e., pending == 0 ). Basically ::ServiceLoop() returns no matter what in this case with zero or one message. -------------------------------------------------------------- Suggested re-wording for section 5.3.3.6.2 An application can use the g() function to put ::ServiceLoop() into a blocking mode rather than its default polling mode. The g() function can be written to cause ::ServiceLoop() to block until it gets one output message, then return on the message it received. This is done by making use of the pending argument to the g() function. This argument simply indicates if there is an output message to be processed or not, for example: int g( void */*context*/, bool pending ){ return pending == true ? 0 : 1 } This g() function causes ::ServiceLoop() to block until the next output message occurs, then returns on processing the first message (i.e. calling its associated callback). -------------------------------------------------------------- Suggested re-wording for section 5.3.3.6.3 - first sentence Alternatively, suppose the application wants ::ServiceLoop() to block until at least one output message occurs, then return only after all the currently pending output messages have been processed. Finally, there is still an unresolved question I have with regards to the pending flag passed to the g() function. Imagine an implementation that must poll the hardware side to find out if a port has a message for it. The ServiceLoop() would poll output ports until it finds a port with a message. It would then transfer the message and call the Receive() callback on the message. The question is, is g() supposed to be called before Receive() or after? If it is called after, pending in this implementation would always be false since by definition the ServiceLoop() is unaware of any messages on the hardware side untill it polls the ports and it always processes messages it becomes aware of immediately. If g() is called before the Receive() (or IsReady()) callback then pending will always be true. Hmm, this leads me to conclude that g() should be called for each `service request' *after* it has been handled by its callback and the pending flag is supposed to indicate if there are any more `service requests' that the ServiceLoop() is aware of pending to be handled. In my example implementation pending will always be false, then. > JohnS: We're in agreement on one issue but not the other. > We agree that g() should be called after servicing the > request. > > But we slightly disagree on the meaning of the pending flag. > The original idea is that the pending flag reflects the > status of the message queues at the time ::ServiceLoop() was > called. So, if there was 1 message at the time ::ServiceLoop() > was called, the message is serviced, then g() is called. > > Pending is set to 1 in this case because there was at least > one message when ::ServiceLoop() was called. Doing it this way > makes it easier for the application to unabiguously control > the behavior of ::SerivceLoop() i.e. make it blocking, polling, > wait for 1 message, etc. Now, take a look at example 5.3.3.6.3. In this example, if pending is always false, haveProcessedAtLeast1Message can never become 1 and g() will always return 1, i.e., the ServiceLoop() will never exit. Yet the ServiceLoop() can process any number of `service requests'. Given that the example is supposed to show how to make ServiceLoop() block until at *least* 1 message has been processed implying it may block until more than 1 message has been processed, I think the example is still valid, although a user might be surprised at how it works with an implementation like the one I've described. Do you agree that an implementation may behave as I described it (never being aware of more than 1 message)? > johnS: Assuming that 'pending' reflects the message status upon entry > to ::ServiceLoop() as I described above, I don't agree. I think > the example should work correctly. ============================================================================== Initial issue on the service loop some questions regarding the SCE-MI service loop: 1) It is not clear to me whether the g() callback must be called for each message transferred or whether the SCE-MI service loop can transfer everything it knows about first, and then call g()? Actually, I am reading example 5.3.3.6.1 again and in that example it states that g() is called for each message processed. Does this refer to only input messages, or both input and output messages? >johnS: >The intent was to call g() (if defined) for each distinct output >message and each distinct input ready callback. In other words, >each time you would call a callback for any reason - be it a >receive callback or an input ready callback. > >g() was not intended to be called for input messages. > >I do agree the wording is vague here and should be clarified. 2) The pending argument of g() is supposed to indicate whether there is at least one message pending. It is not clear whether this refers to input messages, output messages, or both. Input messages makes sense to me, but it may not be possible for the service loop to know whether output messages are pending on the hardware side. In the fourth paragraph from the bottom of p. 43, there is a distinction between messages `pending to be sent' and 'arriving messages'. This would seem to support the interpretation that only input messages figure in the pending argument. >johnS: >I agree there was some additional vagueness in the spec. Actually >the intent here, again, was output messages and input ready >notifications, and distinctly *not* input messages. In otherwords, >only things coming from hardware. The flag is 1 if there is at least >one message pending from hardware when ::ServiceLoop() is called and >0 if ::ServiceLoop() is called at a time when the S/W side is aware >of no messages pending from the hardware.