Registration

Draft 2001-08-27

Registration is used to customize ICU services. This allows applications, for example, to effectively modify the US locale to use a slightly different date format, or collation. Once modified, any call (in that address space) will return the different service. This also allows ICU to emulate the behavior of OS services such as Windows, where the current locale may in fact have customizations.

In practice, this works as follows. Suppose we have the service xxx (collation, format, ...), and call:

uxxx_registerInstance(X, myLocale);

What this does is clone X and add it to an internal registry for the service. By performing this action, the results should be just as if X were in the myLocale resource bundle for the service; overriding what was there (if anything). That affects what happens with getInstance in any subsequent calls, as shown in the table below.

Note: For each resource bundle, there is a resource cache. This caches strings, arrays of strings, etc. Normal resource fallback is used.

For each service, there is a service cache. This is different than the RB cache, since it contains objects (or C pseudo objects) of the type returned by getInstance on that service. The match is exact; no fallbacks.

It is important to distinguish these two caches.

Locale RB contains What getInstance returns in each case
after we register X for:
root fr fr_BE fr_BE_Brussels fr_BE_Brussels_Q
(RB doesn't exist)
root Y X Y Y Y Y
fr <empty> X X Y Y Y
fr_BE Z Z Z X Z Z
fr_BE_Brussels <empty> X X X X Z
fr_BE_Brussels_Q n/a X X X X X

The most straightforward way to code this is to add one step to the implementation of getInstance, which will then look like the following (Step D is the only new step):

A. Let L_request be the requested locale
B. Look in the service cache under L-request. If there is anything, return a clone of it.*
C. Do the normal resource lookup, and get two pieces of information:

a. R = the resource
b. L_found = the resource bundle that we got the resource out of.

D. Probe the registry list from L_request up to L_found. If there is anything matching, set R to that thing.
E. Cache R in the service cache under L_request, and return a clone of it.*

* the cloning must be done unless the service object is immutable.

This also means that registerInstance should flush the cache of service objects (we could be smarter and only flush part of it, but it is simpler to just flush it all, and in practice the performance cost isn't worth the complication).

This is pretty straightforward. There is one wrinkle. If we didn't find a resource bundle in the normal chain (e.g. because fr, fr_BE... don't exist), then we fallback to the default locale. Then in step D you have to search, not from L_request up to L_found, but from defaultLocale up to L_found.

A test needs to be added that basically does the above chart, to verify the behavior.