TechieVarta with C++ Guru

Icon

Just another Techie Varta

Domain Specific Embedded Langauge

We typically program in a general purpose programming language like C, C++, Java, Perl, etc. These languages are designed to solve all the problems of the world and no problem in particular. However, it will be a lot more elegant if sound processing library exposed a sound specific language, an image processing library exposed an image processing specific language not just API calls which is the case currently. In effect these will enhance overall general purpose language. These languages are called Domain Specific Embedded Language (DSEL).  For example:

result  = src * dest;

should multiply two numbers for arithmetic domain. For images, it may layer the two images, for music this expression may allow mixing of the two tunes. As you probably know, in C++ this can easily be achieved using operator overloading. But, the DSELs probably want to be significantly more expressive than depicted above. C++ is probably the best language for defining a DSEL since it allows rich set of operator overloading and metaprogramming constructs to implement your language. This article compares various programming language’s capability to define DSEL.

It is possible to define a complete DSEL manually in C++. However, anything beyond overloading of small set of operators can be time consuming. Boost 1.37.0 now includes Boost.Proto. The Boost.Proto provides facilities to quickly develop DSEL. From Boost.Proto documentation:

Expression Templates are an advanced technique that C++ library developers use to define embedded mini-languages that target specific problem domains. The technique has been used to create efficient and easy-to-use libraries for linear algebra as well as to define C++ parser generators with a readable syntax. But developing such a library involves writing an inordinate amount of unreadable and unmaintainable template mumbo-jumbo. Boost.Proto eases the development of domain-specific embedded languages (DSELs). Use Proto to define the primitives of your mini-language and let Proto handle the operator overloading and the construction of the expression parse tree. Immediately evaluate the expression tree by passing it a function object. Or transform the expression tree by defining the grammar of your mini-language, decorated with an assortment of tree transforms provided by Proto or defined by you. Then use the grammar to give your users short and readable syntax errors for invalid expressions! No more mumbo-jumbo — an expression template library developed with Proto is declarative and readable.

In short, Proto is a DSEL for defining DSELs.

Boost.Proto uses template meta-programming to implement the help bild DSELs quickly and efficiently. Boost.Proto can be slightly overwhelming for the first time users and specifically those who are not used to of templates meta-programming. If you want to use Boost.Proto remember to read the user’s guide a couple of times before trying it out.

Good luck.

Happy DSELing.

Shared Memory based C++ programming

When it comes to shared memory based programming, we C++ users have traditionally found our selves at disadvantage. Most our beloved constructs like shared pointers, various containers, scoped locks, etc. don’t work very well when programming in C++. In addition, we cannot place objects which use inheritance in shared memory since the virtual pointers cannot work in shared memory. These limitation has implied that the shared memory is rarely used in C++ programming. Whenever it is used, the object placed in the shared memory are more like C constructs rather then C++ constructs. This is pity since using shared memory provides significant performance advantage in certain conditions.

Boost 1.35 includes Interproces which provides C++ based programming environment for shared memory. The facilities provided are:

  • Shared memory based pool of memory and capability to new C++ objects from this pool
  • Mutexes placed in the shared memory
  • Various smart pointers
  • Various STL-like containers which can be placed in shared memory. These containers include maps, deque, set, list, flat_map, flat_set, slist, and string

In addition various boost containers can be placed in shared memory. These containers include the multi-index container.

Hopefully these constructs make placing objects in shared memory a little easier for you all. Please note that placing data in shared memory has traditionally been dangerous due to complexity in debugging crashes, not easily understood deadlocks, etc. Please use shared memory based containers carefully.

C++ Monitor Pattern

Locking is an integral part of concurrent programming. A usual class used with threads looks like:

class A {
void F() {
ScopedLock l(m);
....
....
}
Void G()
{
ScopedLock l(m);
....
....
}
mutex m;
};
This guarantees that the class data part of class A are always protected from multiple thread access. However, this code is fragile and difficult to maintain. It moves the responsibility of maintaining concurrency to the class writer. Also, sooner or later somebody will make a change of the following form:

Void G()
{
ScopedLock l(m);
....
....
F();
}

This will deadlock unless you were using recursive mutex.

Also, a construct like this is difficult to use if you are trying to use third party library like STL. For example, let us say you were using std::map. In order to enforce appropriate concurrency control you must wrap every map method you are going to use with a lock that implies you must implement a forwarding class which takes the user argument performs a lock and then call the map function. This is tedious, time consuming and absolute waste of time.

Won’t it be nice if there was a way to generically wrap class and provided method forwarders? The forwarder will provide the lock/unlock capability and the class implementer will not have to worry about concurrency issues. Welcome to monitor pattern. This pattern was first introduced in this paper by Douglas Schmidt.The monitor object guarantees that only one method runs within an object at any given point of time. Because the monitor pattern guarantees that there is any need to perform locking within class methods.

One of the C++ monitor pattern implementation is part of libpoet. ACE provides another implementation of the monitor pattern. I am sure there are other implementations. The libpoet implementation is partially based on the this paper by Bjarne Stroustrup. The library includes two implementations of the monitor pattern. One is based on smart pointer and the other is based on inheritance and has additional functionality. In most cases the pointer based implementation is sufficient and is considered in this post.

The monitor pointer is implemented as smart pointer and is called monitor_ptr. Like any other smart pointer it provides an object wrapper. The wrapper in this case takes a lock before the object is called and releases the lock once the object call is complete.  To use the class A defined above with monitor_ptr we will remove the locks from the class and wrap A as follows:

poet::monitor_ptr<A>  a(new A);

Now calls to  a->F() and a->G() will result in automatic locks taken by the monitor_ptr and call to G() will wait till call to F is complete.

class A {
void F() {
....
....
}
Void G()
{
....
....
}
};
Look no locks. If we need to use a map with concurrent programming we will write something like:

poet::monitor_ptr< std::map<int, std::string> > m(new  std::map<int, std::string>);

We will now access the monitored map using something like:

m->insert(1,std::string("abc"));

without worrying about the locking.

The inheritance based implementation provides additional functionality since it can use condition wait constructs.

Of course it will be much nicer to have a language level support (similar to synchronized keyword in Java) for the monitor pattern. That is a lot more elegant but till the language supports it we will have to live with the smart pointer based implementation.

C++ Weak Pointers

C++ TR1 has added concept of weak pointers. Most of the C++ developers understand use of shared pointers but they don’t understand use of weak pointers very well.

Weak Pointer Definition

According to boost:

The weak_ptr class template stores a “weak reference” to an object that’s already managed by a shared_ptr. To access the object, a weak_ptr can be converted to a shared_ptr using the shared_ptr constructor or the member function lock. When the last shared_ptr to the object goes away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, and weak_ptr::lock will return an empty shared_ptr.

There is no way to directly access underlying resources managed by the weak_ptr. In order to access the underlying pointer the weak pointer must be converted to a shared_ptr using lock or shared_ptr constructor.


shared_ptr<int> p(new int(5));

weak_ptr<int> q(p);

// some time later

if(shared_ptr<int> r = q.lock()) {

// use *r

}

Weak Pointer Usage

This all looks interesting but where will one use it. DDJ covered this subject in one of its articles. Consider an application where thread reads messages from a queue operators on it and then sends response back to the queue. This is tricky if the processing of the message can take a significant time. In order to correctly send back the response the message must hold a reference to the queue. The problem is that the queue may close before the response is ready to be sent. One possible solution is to store shared pointer to queue in the message structure:

shared_ptr<QueueType> q;

struct {

shared_ptr<QueueType> q;

} MessageType;

MessageType m;

m = q->Get();

m.q = q; //m.q holds a shared reference to the queue

...

...

m.q.Send(data);

If the queue is closed after putting a reference to the queue in the message, the queue cannot be destroyed since it is shared pointer. In some of the applications number of messages may be 1000s and can significantly delay queue destruction. A far better alternative is to put a weak_pointer to the queue in the message structure and check the queue state before calling the send. The modified code looks like the following:

shared_ptr<QueueType> q;

struct {

weak_ptr<QueueType> q;

} MessageType;

MessageType m;

m = q->Get();

m.q = q; //m.q holds a  weak reference to the queue. If the queue is closed, the underlying object can be destroyed and resources reclaimed.

...

...

if (shared_ptr<QueueType> realq = m.q.lock() ) {

realq.Send(data);

}

This code segment allows early destruction of queue to reclaim resources.

Static Assert in C++0x

This is post in the C++ Reference series on this site.

All the C++ programmers have used static asserts some have used Loki version, others have used Boost version or created their own. However, in all cases the error messages generated by Static Assert are incomplete. A language level support is needed to correctly support Static Assert.

The C++0x adds Static Assert to solve this specific issue. The synatx for static assert is something like:

static_assert(sizeof(int) == 4, "Size of int is not 4 bytes.") ;

On any machine where the sizeof(int) is not 4, the compilers should correctly generate error message “Size of int is not 4 bytes”. Sweet.

Null Pointer and C++

This is part of C++ Reference series.

C++ is a strongly typed language except when it comes to null pointers. 0 is used both to represent a null pointer and integer value zero. This can cause nasty issues since 0’s type cannot be determined. C++0x adds a new reserved word nullptr to solve this issue.

nullptr is zero pointer that can be converted to any pointer type.

C++0x Auto Types

This is part of C++ Reference series.

Several OO languages including SmallTalk, Python, Ruby, etc have a way to creating new variables with the type of existing variables. In C++ to create a variable, the program always had to know the type.

Starting C++0x this restriction goes away. C++0x adds support for auto-types. For example it is now possible to code:

auto a = b->c;
auto a(b->c);

Both these statements will create a variable ‘a’ with type b->c and assign it value of b->c.

No need to  know the type of b->c. Why do we need autotypes. We thought type safety is important. Let us consider the following code segment:
for (std::vector<int>::iterator it= vi.begin(); it!=vi.end(); ++it)

with auto types this simplifies to:
for(auto vi::iterator it = vi.begin(); it  != vi.end; ++it)

Significantly less verbose and more maintainable code. We can change type of vi from vector to list, deque, etc. without changing type of every iterator.

The code no longer cares about type of vi. It just declares an iterator of the type vi::iterator.

In addition, for memory allocation it is now possible to say:

auto* a = new auto(b->c); // new object of the type b->c and assign it to a new variable of type pointer to b->c.

More interesting syntax:

auto p = std::string("xxx"); // p has type of std::string
auto p[] = “xxx”; // p has type of char[4]
auto* p = “xxx”; // p has type char*
auto a = 10; // a has type integer

References:
http://std.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1527.pdf

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=219