One result of the recent string landing (see bug 231995) is that it is no longer possible to declare global (or static) named literal strings using NS_NAMED_LITERAL_C?STRING. (In fact, this actually applies to all string classes.)

The problem is that the new string classes depend on global data being initialized properly in XPCOM. So, any global or static references to a string class could run the risk of not being initialized properly. On some platforms, this problem does not show up. However, the Mac OSX static build of Mozilla is affected. In fact this problem is the reason why there haven't been any functional nightly builds for Firefox on Mac OSX since the string rewrite landed (see bug 234916 for details).

The patch for bug 234916 eliminated all global and static declarations of NS_NAMED_LITERAL_C?STRING. Hopefully, there are no others lurking in the tree. My hope is that this note will help deter folks from introducing more of these.

So, if you need to reference the same set of literal strings many times in your code, you'd probably want something like a static NS_NAMED_LITERAL_STRING. Since that's not possible anymore, I thought I'd outline some alternatives:

1) Do you really need NS_LITERAL_STRING? Can you get by with |static const PRUnichar text[] = {'x','y','z','\0'};|? In many cases, this is inconvenient. But, it's always worth considering.

2) Are you writing a service (or some other object that is only allocated once)? If so, how about declaring your literal strings as member variables. There's some new machinery added to nsLiteralString.h that helps make this easier. For example, you can do the following to declare literal strings as member variables:

   class MyService : public nsIMyService
   {
   public:
     MyService();
     ...

   private:
     const nsLiteralString kFoo;
     const nsLiteralString kBar;
   };

   MyService::MyService()
     : NS_LITERAL_STRING_INIT(kFoo, "foo")
     , NS_LITERAL_STRING_INIT(kBar, "bar")
   {}

This mechanism was used to convert the static literal strings in nsWebScriptsAccess.cpp over to non-static, member variables.

3) Is your XPCOM module accessing a set of literal strings repeatedly? If you can't stick them on a service, then how about declaring a structure full of nothing but your literal strings. Then allocate this structure from your XPCOM module constructor and delete it from your XPCOM module destructor. Like this:

// some header file included by the .cpp files comprising your XPCOM module:

   struct MyLiterals
   {
     MyLiterals();

     const nsLiteralString kFoo;
     const nsLiteralString kBar;
   };

   MyLiterals::MyLiterals()
     : NS_LITERAL_STRING_INIT(kFoo, "foo")
     , NS_LITERAL_STRING_INIT(kBar, "bar")
   {}

extern MyLiterals *gMyLiterals;


// the .cpp file containing your XPCOM module declaration:


MyLiterals *gMyLiterals;

   PR_STATIC_CALLBACK(nsresult)
   MyModuleConstructor(nsIModule *aModule)
   {
     gMyLiterals = new MyLiterals();
     if (!gMyLiterals)
       return NS_ERROR_OUT_OF_MEMORY;
     return NS_OK;
   }

   PR_STATIC_CALLBACK(void)
   MyModuleDestructor(nsIModule *aModule)
   {
     delete gMyLiterals;
     gMyLiterals = nsnull;
   }

   NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(MyModule, gComponents,
                                      MyModuleConstructor,
                                      MyModuleDestructor)

// now, in any of your .cpp files you can just reference your literals directly:

   NS_IMETHODIMP
   MyClass::GetFoo(nsAString &_retval)
   {
     _retval = gMyLiterals->kFoo;
     return NS_OK;
   }


Yes, this 3rd option seems much more complicated then simply declaring NS_NAMED_LITERAL_STRING's at global scope, but believe it or not it does result in less generated code (at least on x86-linux since global data access is PLT-relative). You can see an example of literal strings being used in this 3rd way by inspecting the code in nsSOAPUtils.{h,cpp} and nsWebServicesModule.cpp.


I hope this helps, and please let me know if you have any questions regarding this "change" ;-)

-Darin

PS. This is nothing new (see http://www.mozilla.org/hacking/portable-cpp.html#dont_use_static_constructors)

_______________________________________________
Mozilla-xpcom mailing list
[EMAIL PROTECTED]
http://mail.mozilla.org/listinfo/mozilla-xpcom

Reply via email to