[interfacekit] Re: Phase 1

>I knew, it is impossible to have a spontaneous consensus on 
>conventions. ;-)
>
>I would like to achieve to goals:
>* Avoid polluting the B_ namespace (e.g. I don't think B_SUCCESS is an 
>option).
>* Make the identifiers self-reflective, i.e. it should be clear, that 
>they have to do with the registrar.
>
>So, what do you think about B_REG_* or BReg::* (or BRegistrar::* for 
>abbreviation phobics)?

Agreed on all points. =)  I think B_REG_* is a good choice.

>Are you content with the message/type constant values? Or do you think 
>they should also lie within the range Be reserved, i.e. 'ABCD' for type 

>constants and '_ABC' for message constants? As discussed, the API user 
>won't get in contact with them.

Hmm, hadn't thought about that.  I think sticking with Be's protocol is 
probably best; developers already know not to step on that range, which 
is really my only concern here.  Going back over the original mail, I 
didn't actually see any constants being proposed, just their #defines 
.. maybe in an earlier mail?

>> Well, at Borland (which is the only other place I've seen using the 
>> 'T' 
>> prefix systematically) the T stood for 'type'.  We would sometimes 
>> joke 
>> that it actually stood for 'turbo' (as in "Turbo C++", etc. =).
>
>Maybe we should keep it then. ;-)

I've always been partial to it. =)

>It may be a good idea to put the list management into a separate class 
>that can easily be exchanged.

Agreed.

>> >The Roster class will implement all roster features. The registrar 
>> >application's MessageReceived() may dispatch the roster messages 
>> >directly to the respective Roster methods. It might not even extract 

>> >the contents of the message, but rather leave that for Roster.
>> 
>> I would likely extract the message contents into parameters for 
>> Roster, 
>> but that's just personal preference; I don't think there's much of a 
>> technical argument to be made either way.
>
>It came into my mind that the application's MessageReceived() will need 

>to handle quite a lot of messages and extracting the fields for all of 
>them at this very method would bloat it. Aside from this less code has 
>to be changed, when we decide to modify a request, and it might be less 

>painful to deal with optional message field. Finally, almost for all 
>requests a reply needs to be sent, and directly using 
>BMessage::SendReply() sounds straighter to me than to get 
>BMessage::ReturnAddress() and pass it to the method.
>But yes, these aren't really technical arguments.

Actually, I think those are pretty decent technical arguments, so I'm on 
board with your proposal. =)

>Yep, they are and I meant it to be a direct replacement for 
>AddApplication() only.
>Some clarifications: The four functions should merely be equivalent to 
>the current functions:
>
>RegisterApp()                  == AddApplication()
>RegisterRunningApp()   == CompleteRegistration()
>UnregisterRunningApp() == RemoveApp()
>UnregisterApp()                        == RemovePreRegApp()
>
>Well, actually I don't know, whether they are equivalent, because I 
>haven't completely understood the original ones.
>Here is how I think the registration process should work. There are two 

>levels of registration, err, actually three: unregistered, registered 
>and registered-running.

I have to admit I was a bit confused by this.  I sat and did a lot of 
head scratching and cogitation.  The central questions were:

1) If AddApplication() takes the team_id, thread_id and port_id as 
parameters, why would it later need to send those very same parameters 
to the roster via CompleteRegistration()?

2) Looking at RemovePreRegApp(), I saw IsAppPreRegistered().  Assuming 
these two are related (which seems reasonable), why/how would an app get 
"preregistered"?

I had no idea, so I went and watched a movie instead. =)  When I came 
back from that, it occured to me that there are two ways an application 
can get launched: directly, and by BRoster::Launch().  In cases where 
the app is launched directly, BRoster::AddApplication() would get used, 
because all the necessary "registration" info is immediately available 
to the launching app.  In cases where BRoster::Launch() is used, three 
vital pieces of information are *not* available when the roster is first 
made aware of the launch: the team_id, thread_id and port_id.  Following 
this train of thought, it seems to me that when BRoster::Launch() is 
used, the app is "preregistered" with the roster, the app is run, and 
when BApplication gets to the point where it would normally register 
itself with the roster it checks to see if it's been preregistered 
(BRoster::IsAppPreRegistered()) and calls CompleteRegistration() if it 
has been.  The app's entry in the roster would then get "moved" from its 
preregistered state to a fully registered state.

The short version is that there isn't a two-stage registration process, 
but two *different* registrations processes: one for direct launches, 
one for BRoster::Launch() initiated launches.

>The BApplication constructor makes the application known to the roster 
>via RegisterApp(). From that time on it appears on the roster, i.e. 
>roster-watchers receive a notification and all others can use the 
>BRoster functionality to query the app -- IsRunning() will return true, 

>and TeamFor() and GetRunningAppInfo() will work. Registered-running is 
>the level on which the application, that is its message loop, is really 

>running. BApplication::Run() will call RegisterRunningApp() which in 
>turn will cause the roster to send the B_ARGV_RECEIVED, B_REFS_RECEIVED 

>and B_READY_TO_RUN messages.

In cases of direct launches, it introduces extra (and unnecessary) 
overhead to send the info necessary for those three messages to the 
roster, only so it can turn around and send them right back.  Maybe it 
would send them for BRoster::Launch() launches, but that doesn't make 
much sense either: BRoster::Launch() could simply call load_image(), 
which takes argc and argv and probably passes them directly to the app.

It's unclear from the docs whether BRoster calls load_image() or the 
roster itself calls it.  Looking at RemovePreRegApp(), my guess is that 
BRoster pre-registers the app with the roster (which returns a token) 
and then attempts to launch it (via load_image()).  If the launch fails, 
BRoster uses RemovePreRegApp() to clear the roster entry.  If the roster 
was actually launching the app, I don't think BRoster::RemovePreRegApp() 
would need to exist.

>> In particular 
>> these
>
>> >params:
>> >- argc: The application's command line parameter count.
>> >- argv: The application's command line parameters.
>> 
>> don't make any sense when BApplication is registering itself -- why 
>> would BRoster care what these are, since the app already knows?
>
>I think, it makes sense. Or at least it makes things easier. If the 
>roster sends B_ARGV_RECEIVED, then those arguments must get there 
>somehow. Well, you might say, that the application could as well send 
>the message itself or just call ArgvReceived(). OK, then this argument 
>may be more convincing: If the application is single/exclusive launch 
>and called the second time, then the argvs must be sent to the already 
>running instance. If the latter is on level registered, not registered-
>running, then it might be better to wait with sending the argvs until 
>its message loop is running. The roster can do that, the new 
>application instance can't.

That last statement isn't actually true.  If an app is single/exclusive 
launch, it can check the roster to see if an instance is already running 
with BRoster::GetAppInfo().  If an instance *is* running, it can use the 
team_id in the app_info struct returned by GetAppInfo() to create a 
BMessenger and send along the B_ARGV_RECEIVED message itself.  Either 
way it's launched, the app is going to get argc and argv -- it makes 
more sense to just have the app deal with them locally than to send them 
over to the roster and have the roster forward them (if necessary) or 
just send them right back.  These same arguments (approximately) apply 
to B_REFS_RECEIVED and B_READY_TO_RUN.

>To summarize my point: The roster can much better deal with the argv 
>stuff, and let it do so makes the BApplication side a lot simpler.

I don't think the first is necessarily true, and I don't see a 
particular advantage to pushing the work onto the roster instead of 
doing it in BApplication.  In fact, we would introduce additional 
messaging overhead by doing so.

>> >params:
>> >- team: The application team.
>> >- thread: The application looper thread.
>
>A correction: The thread argument is not needed here, but in 
>RegisterApp(). It is not the looper thread, but the application's main 
>thread (which may differ). The same of course goes for the message 
>protocols.

How are the threads going to differ?  The docs explicitly state that 
BApplication "takes over" whatever thread it's in.

>AFAIK most system messages don't show up in MessageReceived(). The 
>hooks are either called by DispatchMessage() or even earlier.

Duh.  Didn't think of that. ;P

>> The whole point of the exercise is to illustrate that 
>> BRoster::IsRunning() returns true before B_READY_TO_RUN is 
>> (theoretically) sent and certainly before ReadyToRun() is called by 
>> BApplication.  In short, I think RegisterRunningApp() needs a 
>> rethink. 
>> ;)
>> 
>> Please correct me if I'm misunderstanding. =)
>
>I hope my attempt for clarification helps.

Yes, I now understand that these functions weren't intended to effect 
the return of BRoster::IsRunning().  Of course, I had to open another 
whole can of worms instead ... ;)

>I'm not sure, if it is really necessary to have a two-level 
>registration, but it seems to me at least convenient. For sure it gives 

>the roster more knowledge, that can be exploited -- e.g. avoid sending 
>an application not running the message loop messages.

I see what you're saying, though it would entail adding a function to 
BRoster (IsLoopRunning() or something).  I think the odds are pretty 
slim of there being messages already waiting in the queue of an app that 
fails to launch, and having a few messages "disappear" once in a blue 
moon doesn't strike me as a problem.  And now that I think about it, how 
would one actually *send* messages to an app that hasn't managed to 
successfully launch?  The only mechanism I can think of is 
BRoster::Launch(), and that will clearly let the caller know if the 
launch failed -- not to mention, it's not likely to try and send 
messages to an app it couldn't launch. ;)

>> >message:    REG_REGISTER_RUNNING_APP
>> >message:    REG_UNREGISTER_RUNNING_APP
>> 
>> Unless I was horrendously mistaken earlier, these two messages should 

>> not be needed.
>
>If we drop the corresponding methods, then I agree. But currently I 
>still like the idea of a two-level registration.

As I said before, I don't think there are two levels in the registration 
process -- there are two *different* registration processes.  Maybe I 
should write up a coherent outline of what I think the process looks 
like ... ??

e

Necessity is the plea for every infringement of human freedom. It is the 
argument of tyrants; it is the creed of slaves.
        -William Pitt, British prime-minister (1759-1806)


Other related posts: