Discovering C++ Idioms in BREW, Page 2
A Singleton should not be directly instantiated (that's why the private constructor) and obviously getInstance() returns the same instance. Let's see how this translates in BREW. Singleton has a unique instance, kept by CPPApp (b_). To access it, Singleton is a friend of CPPApp. On the other hand, the creation of b_ has to be done by CPPApp (in OnAppInitData()) and has to be inhibited at compile time in other contexts (private constructor). This implies that CPPApp has to be a friend of Singleton. An example of using Singleton is presented in test1().
It was mentioned before that simply using CPPApp::sharedValue might create some discomfort for the user. There are some problems with this design:
- A proliferation of public variables in CPPApp
- Class Test has no real variable sharedValue; it has to create a link between CPPApp::sharedValue and a member static function to mimic this
A more complex design might alleviate these issues:
class CPPApp : public AEEApplet
{
//....
private:
friend struct Static;
void* statics[4]; //simple container
};
struct Static
{
template <class T>
static typename T::STATIC_TYPE staticValue()
{
CPPApp* c = CPPApp::getInstance();
return *static_cast<typename T::STATIC_TYPE_PTR>
(c->statics[T::getUID()]);
}
template <class T>
static void staticValue(const typename T::STATIC_TYPE t)
{
CPPApp* c = CPPApp::getInstance();
c->statics[T::getUID()] = &t;
}
};
template <class TP>
struct StaticBase
{
typedef TP* STATIC_TYPE_PTR;
typedef TP& STATIC_TYPE;
};
Static defines the manipulation pattern and StaticBase is a simple policy class for manipulating types. There is a container of static variables in CPPAppp, Every static variable is uniquely identified by type and an unique ID, a simple int in this case. Let's take, for example, a simple class having two static variables:
struct A : public Static
{
StaticA a;
StaticB b;
};
This is how the two variables have to be defined to be unique:
struct StaticA : public StaticBase<int>
{
static size_t getUID()
{
return 0;
}
};
struct StaticB : public StaticBase<int>
{
static size_t getUID()
{
return 1;
}
};
Now, CPPApp has an automatic way of keeping track of static variables (of course, the array will be replaced by a container in real life). They are strongly typed and user classes now own them:
void test2()
{
Writer writer;
int val = 777;
A::staticValue<StaticA>(val);
StaticA::STATIC_TYPE i = A::staticValue<StaticA>();
writer.WriteLine(i);
i = 2345;
writer.WriteLine(A::staticValue<StaticA>());
val = 888;
A::staticValue<StaticB>(val);
writer.WriteLine(A::staticValue<StaticB>());
A::staticValue<StaticB>() = 4567;
writer.WriteLine(A::staticValue<StaticB>());
}
Resulting Context:
- We've obtained a behavior consistent with static semantics.
- But, additional complexity was added.
EverLoad
Problem:
- How does one use the new/delete operator in BREW?
Forces:
- BREW doesn't offer a predefined new/delete global operator
- New/delete operators[7] are of significant importance in BREW (see "Stack Starvation" for a reason why heap allocation is unavoidable)
Solution:
- Always overload the new/delete operator (always in pairs)
- Always overload the new[]/delete[] operator
- The new/delete operator can be overloaded at a global scope or class scope. A good rule of the thumb is to implement a global overload and to use class scope for specific memory allocators[4]
- Exercise care in switching compilers; there are ANSI/ISO C++ incompatibilities in this area (notably "inline" and operator delete accessibility are pertinent to this topic)[8]
Example:
//global scope
void* operator new(size_t sz);
void operator delete(void *p);
void* operator new[](size_t sz);
void operator delete[](void *p);
class A
{
public:
static void* operator new(size_t sz);
static void operator delete(void *p);
//....
}
Related Patterns:
Variable Allocation
What's Next?
The next article will continue this discussion, presenting other idioms.
References
[1] http://brewforums.qualcomm.com
[2] http://brew.qualcomm.com/brew/en/developer/resources/ds/faq.html
[3] http://brew.qualcomm.com/brew/en/developer/resources/ds/okb.html
[4]
- Small Memory Allocation - Part 2
http://www.developer.com/ws/brew/article.php/3323091 - Small Memory Allocation - Part 1
http://www.developer.com/ws/brew/article.php/3315011
[5] GOF. Design Patterns: Elements of Reusable Object-Oriented Software, Addison Wesley. 1994
[6] John M. Vlissides. Pattern Hatching: Design Patterns Applied, Addison Wesley. 1998
[7] For a complete discussion of the new/delete operator, see Scott Meyers. More Effective C++, Addison Wesley. 1996
[8] http://fusshuhn.ourfamily.com/cppincomp.html
Download
Download the accompanying code file here (77 Kb).
