Skip to main content

Posts

Resource Management Patterns

Resource Acquisition catagory: *********************************** Lookup: Naming service, Trading service, Directory service Lazy Acquisition: Resource proxy, web browser image proxy and deferred image download, Java JIT compiler. Good for scalability and low latency. Eager Acquisition: Good for predictability, bandwidth pre-allocation, pre-connect. Partial Acquisition: Acquire resoruce in steps. Resource Lifecycle catagory: ******************************** Caching: for performance, identity of resources is important. Pooling: for boundedness, identity of resources is not important. Coordinator: To provide commit-or-rollback semantics. Similar to strong exception safety guarantee. Best example: two-phase commit protocol (prepare() and commit()) Resource Release catagory: ******************************* Leasing: Free up unused/invalid resources/service location references after some pre-determined lease time if not accessed. Renew lease if accessed in between. Evictor: Used with cachin...

Upcoming C++ language changes (C++0x)

C++ programming laguage is undergoing interesting language changes. The delegating constructor is a useful new addition which changes the semantics of throwing an exception from a constructor. As of now, exception raised during execution of any constructor of a class (including base-member initialization list), the destructor of that class is not invoked (for that object). This is because the object never really got created successfully. This will be now longer be true after C++0x is released!!! Below is a list of some of the upcoming language changes. * Nearly all of the Library Technical Report (TR1) * Auto type deduction * Delegating constructors * Right angle brackets * extern templates Source : Highlights of the April 2006 ISO C++ meeting (Herb Sutter)

Swapping two integers in a one liner

I found some really cool one liner solutions to swap two integers without using a temporary variable. These were posted on "C/C++ Programming Puzzles" community on www.orkut.com . Some of them are listed here. 1. a+=b-=a=b-a; 2. a/=b=(a=a*b)/b; 3. a^=b^=a^=b; same as a=(b=(a=b^a)^b)^a; (Thanks to Robert Vukovic) 4. b=a+b-(a=b); Each individually are cool solutions. But all of them have one big problem. These are not portable! C standard says that when a value of an operand is changed in the same expression at some other place, then the result of the expression is undefined. Try running the program on gcc with -Wall option. All the above one liners (which are really cool to begin with!) are plagued by that. So I feel the most portable way to achieve the goal is: a = a xor b; b = a xor b; a = a xor b; (by Harpreet) Unfortunately it is not a one liner.

Double Checked Locking Pattern, volatile keyword and memory barriers

Double Checked Locking Pattern (DCLP) is used to initialize singleton only once in a multithreaded application and also to avoid cost of acquiring lock everytime singleton is accessed. DCLP should be considered in two different dimensions. (1) CPU instruction reordering (2) Multi-processor machines. In a single threaded application running on a modern CPU, use of volatile keyword in DCLP is really important. volatile keyword prevents any aggressive instruction reordering that modern CPUs might do. The static instance pointer of the singleton and the singleton by itself (both) should be volatile for the magic to work! volatile exists for special purposes: (1) the content of a volatile variable is “unstable” (can change by means unknown to the compiler), (2) all writes to volatile data are “observable” so they must be executed religiously, and (3) all operations on volatile data are executed in the sequence in which they appear in the source code. The first two rules ensure proper readi...

Some C/C++ standards trivia

"Maximal munch" rule of C++ compiler tokenizer causes ">>" token to be indentified as a right shift operator. Basically, the tokenizer tries to match a string with longest possible "known" token. Because of this, in nested templates, X<Y<int>> can't be parsed sensibly as the ">>" is not split into two ">" (as desired by programmer). A simple solution is to put a space between two consecutive ">"s. This would have otherwise required context sensitive parsing. But C++0x standard promises to relieve programmers from this seemling vexing parse of C++. One of the few language changes in C++0x is to allow "X<Y<int>>! Another addition is "extern template" , which provides a syntax for telling the compiler that a specific template instantiation will be provided somewhere else. For more information please see: DDJ - More News From the Front C99 standard defines a new (not ne...

C++ templates should define traits

Exposing type information "out" from a class template appears to me as a good practice. For example, a class template Array<T> should define a trait which looks something like typedef T Array:TYPE in its public interface. Not only the parameter type, it should also expose any composite types used inside the template. There are several good reasons behind it. 1. Member functions of the class can make use of the traits. 2. You can avoid typing really long names using these quick typedefs. 3. Consistency. 4. Other classes can make use of the traits. For example, derived classes. Sometimes it is simply not possible to write a non-template derived class of a parameterized class if the parameterized base-class does not expose necessary traits. For example, template <typename T> class Array; template <typename T> class Access_Table { Array<T> array_; }; A new class AT_Adapter wants to adapt Access_Table<T> by adding get_array() functio...

Really short STL notes

My STL notes after reading Effective STL by Scott Meyer. For most of the points below, there are subtle important reasons for that. The reasons are not mentioned here as it would be too long. Please read Effective C++ by Scott Meyer. 1. Use member insert function instead of copy algorithm and inserter. 2. Minimize capacity: string (s).swap (s) Clear and minimize capacity : string ().swap (s) 3. Associative containers use equivalence (strict weak ordering) and not equality. Equivalence: !(w1 < w2) && !(w2 > w1) In strict weak ordering, equal values are not equivalent! Therefore, Comparison function should return false for equal values when equivalence is expected. 4. Use map::operator [] to modify/retrieve existing elements in the map Use map::insert to add new elements 5. Iterator can be implicitely converted to reverse_iterator. reverse_iterator to iterator: use member base() function. const_cast works for conversion from const_iterator to iterator o...

STL short / one liners

A very nice collection of wrappers is available on Stackoverflow . 1. Copy everything in the a container to std::cout (e.g. std::set<std::string> c; ) std::copy (c.begin(), c.end(), std::ostream_iterator <std::string> (std::cout, "\n")); 2. Clear vector v and minimize its capacity (potential number of elements it can hold without resizing). vector <std::string>().swap (v); Yes! It is a swap with an empty temporary!! 3. Remove all integers of value = 0xDeadBeef; std::erase (std::remove (c.begin(), c.end(), value), c.end()); This is known as erase-remove idiom. 4. Invoke a member function on all the elements of the container. std::for_each (c.begin(), c.end(), std::mem_fun (&Class::function)); 5. Copy one container to other std::copy(V.begin(), V.end(), L.begin()); 6. Fill an array with random numbers std::generate(V.begin(), V.end(), rand); 7. Read a file of integers in a set std::istream_iterator <int> data_begin (std::cin),...

Standard concurrency support to C++

The "Concurrency Revolution" is coming at us fast (to gulp us) whether you are ready for it or not! Please see a presentation (audio/video) by Hurb Sutter at parc. Our favorite language, C++, is also not far behind in providing standard concurrency support to the language/library. Please see: Threads and memory model for C++. I feel there is exciting time ahead and a lot of really cool stuff to continue this blog for many years to come!

What is a "thunk"?

A "thunk" appears to be an overloaded term in computer science. Use of the word "thunk" goes back to Algol 60 implementation. In general, as I understand it, thunk is a function which is used to replace something. More often than not, it is auto-generated. This "something" could be an expression (in a programming language) or an address. In programming language world, a known usecase is call-by-name. The mechanism of dynamic linking (.DLL/.so files) uses local thunks to invoke dynamic linker at run-time and replace the thunk with the actual function for all the later invocations of the function. Please see how this technique can be exploited to modify program behavior at run-time . In the C++ world, transparent replacement of addresses is very useful. An example is, adjusting pointers when virtual functions are invoked using one of the many possible base classes of the derived most class when multiple inheritance is involved. Depending upon which base cla...

C++ object layout implementation

There are several cool implementation techniques of C++ object layout, especially when multiple inheritance, virtual functions and virtual inheritance is involved. Understanding the consequences of these rather advanced concepts in the language on the implementation of the language is quite interesting. There are several "gotchas" involved. Example, it is highly recommended to invoke the virtual base class's constructor in the derived most class when there is a diamond shape inheritance hierarchy. It is a pretty eloborate subject so I won't duplicate the same thing here. I would just assemble some really good articles on the topic. Lippman's book "Inside The C++ Object Model" talks about it at length. Please see: C++ Object layout in multiple inheritance Adjustor thunks Multiple inheritance in C++ (Stroustrup)

Functions inside constructor should throw (if they fail)

This is a for constructors, which do non-trivial resource allocation and initialization using helper member functions in the class. Exceptions raised in such member functions should be propagated upto the constructor and not eat them. In other words, such member functions should throw exception if they can't satisfy their contract even though they provide strong exception safety guarantee. Exception propagated upto the constructor will be automatically propagated where the object is being constructed indicating failure in object construction. Otherwise, silently eating exceptions during object initialization will create an object in an inconsistent state. The scope in which it is created will never know that actually the object construction failed. If object construction can be reasonably performed even in the face of exception, then it need not be propagated out. Example, LStack: A Stack implemented as a linked-list. LStack::LStack (const LStack & s) { this->copy_all_nodes...

Why overloaded ++ operator signatures are different?

The canonical form of overloaded pre-increment and post-increment operators for class Foo are declared in the following way in C++. /// Preincrement operator Foo & operator++ (void); /// Postincrement operator const Foo operator++ (int); The int in the post-increment operator is obviously to disambiguate between post and pre forms of the operator. Then, why is the return type different? As many other C++ features, this one also has a subtle meaning! In C++, for ints, you can write ++i = k; but not, i++ = k; This is because, i++ results in a Rvalue to which you can't assign. Unlike i++, ++i results in a Lvalue to which you can assign which is infact ( incremented ) i itself. Not that ++i = k; has a great importance, but it is a fact that C++ has been designed that way. I would be interested in knowing the reason. One reason is that i++ = k; is not allowed is that it is just ambiguous. but ++i = k; is not ambiguous. A const in the return type is also required to disallow...

Curiously Recurring Template Pattern (CRTP)

It is a C++ idiom in which inheritance and template type parameters are cleverly integrated to generate flexible types at compile-time. In CRTP, a template class inherits from its own template parameter. For example, template <typename Base> class MixinOne : public Base {}; This technique is also one of the ways of using "Mixins". Here class Mixin helps to "mix in" some useful functionality into any class type Base. For example, class Mixin can make class Base a singleton. Complete code example is here. In this case of CRTP, a hierarchy (a new class plus inheritance relationship) is created when Mixin template is instantiated. Thus hierarchy creation is differed till the instantiation of the template. This is pretty cool! Moreover, CRTP can appear in a different fashion in which a class passes itself as a template parameter to its base class. For example, class Derived: public MixinTwo<Derived> {}; The non-template class Derived inherits interface/stru...

C++ templates are turing complete

Here you will find a short C++ program that takes more than 24 hrs to compile on a dedicated dual processor, 1GB memory machine!! Here we go... template<int Depth, int A, typename B> struct K17 { static const int x = K17 <Depth+1, 0, K17<Depth,A,B> >::x + K17 <Depth+1, 1, K17<Depth,A,B> >::x + K17 <Depth+1, 2, K17<Depth,A,B> >::x + K17 <Depth+1, 3, K17<Depth,A,B> >::x + K17 <Depth+1, 4, K17<Depth,A,B> >::x; }; template <int A, typename B> struct K17 <16,A,B> { static const int x = 1; }; static const int z = K17 <0,0,int>::x; int main(void) { } Source: C++ Templates are Turing Complete by Todd L. Veldhuizen This program is taken from the above paper which takes unreasonably long to compile. I belive, a simple dynamic programming solution will reduce the exponential time required by this program to compile to polynomial time. I also believe, it might be quite difficult to apply dynamic programming solut...

const overloaded arrow operator

I think it is a good idea to have const-overloaded arrow operator in counted pointer idiom though the Coplien's book does not say about it. This is required to "carry forward" the const-ness from the handle object to the body pointer held inside the handle. Counted body idiom is useful when you do not want to add corresponding (mirror) functions in handle class when you add functions in the body class. Handle class can actually be template. (CORBA _var classes?) The arrow operator takes care of "automatic" forwarding. class String // this is handle { ... Stringrep *operator -> () const { return b_; } private: Stringrep *b_; } class Stringrep // this is body { void func (); // a non-const function. } main() { const String s (new Stringrep); s->func (); // invokes a non-const function of stringrep (body) when handle object is const. } In order to prevent this undetected mishap declare vonst-overloaded arrow operators. class String { ... const Strin...

Subtle function overloading

Quite often I rediscover my own old posts and learn new things from it. This time I am revisiting the very first post http://cpptruths.blogspot.com/2005_06_19_cpptruths_archive.html I came up with a puzzle to "entertain" you guys! Predict the output of following program. You know where to look at for the explanation. const int FIRST_TIME = 1; template <typename T> void func (T &) { static int var; ++var; if (FIRST_TIME == var) cout << "Printed once." << endl; else cout << "Printed more than once." << endl; } int main(void) { int a1[4]; int a2[5]; func (a1); func (a2); } OUTPUT: Printed once. Printed once. !! I would rather have a static checker to guard me against such subtle things.

What's wrong with C++?

I whole heartedly agree with this article!! What's wrong with C++? by Bartosz Milewski src: http://www.relisoft.com/tools/CppCritic.html -------------------------------------------------- Some time ago NWCPP (Northwest C++ Users Group in Seattle) organized a public panel on the future of C++, with Scott Meyers, Herb Sutter, and Andrei Alexandrescu. I started thinking about C++ and realized that I wasn't that sure any more if C++ was the answer to all my problems. I wanted to ask the panelists some tough questions. But I was there for a big surprise--before I had the opportunity to say anything, they started the criticism of C++ in the earnest--especially Scott. One of the big issues was the extreme difficulty of parsing C++. Java and C#, both much younger languages, have a multitude of programming tools because it's so easy to parse them. C++ has virtually nothing! The best tool one can get is Microsoft Visual Studio, which is really pathetic in that department (I haven...

Memory management idioms

This time lets briefly look at three structural idioms discussed in Coplien's book, Advanced C++ programming styles and idioms. Handle and Body: Handle and body are logically one entity but physically two. This separation allows handle to be much smaller in size than the body. Handle and body are both classes. Because they are logically same entity, there are several consequences: handle can be passed instead of body wherever body is required (efficient). To be logically same, handle and body needs to have exactly same interface. Any addition to body class interface needs a change in the handle class (maintenance). Handle class delegates all function calls to the body. (extra function call). Handle manages memory and the body manages the abstraction. This type of structure is typically used in reference counting . Though hidden from the client, body class pollutes the global namespace. Important thing to note here is that though, both the classes are in global namespace the inst...

const/volatile integrity violation

This time I am going to point you at two short, interesting articles on const integrity violation which is also applicable to volatile modifier. Basically it talks about the following feature of C++: GIVEN int *i; const int *p = i; // is allowed BUT const int** p = &i; // is not allowed !! AND const int*& p = i; // is also not allowed !! How to fix it? GIVEN int *i; const int *p = i; // is allowed BUT const int* const * p = &i; // is allowed !! AND const int* const & p = i; // is also allowed !! FAQ: http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17 AND http://www.gimpel.com/html/bugs/bug1561.htm