Compile Time Dynamic Proxies in C++

These are my notes for compile time proxies generated from C++.  I’m not sure I will be able to understand them in the future, so good luck to you if you feel the need to read them.

Java Dynamic proxies are a well established means of reducing code by extracting a cross cutting concern. The C++ philosophy is more “Why put off to runtime that which can be performed at compile time.” How would we get the same kind of flexibility from C++ as we get from Java Dynamic proxies?

First, we would need a handful of helper classes that mimic the introspection API of Java. If we have the simple classes of Method, Field, Parameter, and Class, we can perform much of the logic we need. Refer to the Java reflexion API to see roughly what these classes should contain and what they do.

Code generation is the obvious approach, and the lack of introspection of the C++ makes abstract syntax tree analysis  it the only viable approach currently available. We can get all the information we require from g++ if we just ask nicely. FOr example, if we add the flag -fdump-translation-unit to g++ we get the file with the AST in an ultra-normalized form. For example, I want to find all of the classes defined in the file generated when I compile ExampleTestCase.cpp. The file ExampleTestCase.cpp.t00.tu on line 414 has:

@1086 identifier_node strg: ExampleTestCase lngt: 15

If we then search for what @1086 means:

adyoung@adyoung-devd$ grep -n “@1086 ” ExampleTestCase.cpp.t00.tu

1749:@783 type_decl name: @1086 type: @554 srcp: ExampleTestCase.h:14
1762:@787 function_decl name: @1086 type: @1093 scpe: @554
2414:@1086 identifier_node strg: ExampleTestCase lngt: 15
4237:@1932 type_decl name: @1086 type: @554 scpe: @554
4242:@1935 function_decl name: @1086 mngl: @2450 type: @2451
28445:@13185 function_decl name: @1086 mngl: @14801 type: @14802
We see that this identifier is used several places, but the two interesting ones are the type_decl lines, and they both refer to entry @554. Most likely the function definitions are something like the constructors. This is the data on that record:

@554    record_type      name: @783     size: @43      algn: 64
vfld: @784     base: @785     accs: priv
tag : struct   flds: @786     fncs: @787
binf: @788

It needs some prettying up, to get it all on one line, but other than that, it looks right. The big thing is the tag: struct that tells us this is a c struct. C++ must be forced to conform to c at some point, so classes become structs.

Let’s take it even simpler.  If we make an empty C++ file, called empty.cpp and compile it with:

g++   -fdump-translation-unit   -c -o empty.o empty.cpp

we get a file with a lot of standard symbols defined:

grep identifier empty.cpp.001t.tu | wc -l
1215

If we add a single static variablle, the venerable xyzzy, we can easily find it in the file:

adam@frenzy:~/devel/cpp/proxy$ echo “static int xyzzy;” >> xyzzy.cpp
adam@frenzy:~/devel/cpp/proxy$ g++   -fdump-translation-unit   -c -o xyzzy.o xyzzy.cpp
adam@frenzy:~/devel/cpp/proxy$ grep identifier  xyzzy.cpp.001t.tu | wc -l
1216

We’ve only added a single line, that looks like this:

@4      identifier_node  strg: xyzzy    lngt: 5

If we now add a Noop struct to that, we get a little bit more info:

adam@frenzy:~/devel/cpp/proxy$ echo “struct Noop{}; static int xyzzy;” >> Noop.cpp
adam@frenzy:~/devel/cpp/proxy$ make Noop.o
g++  -fdump-translation-unit    -c -o Noop.o Noop.cpp
adam@frenzy:~/devel/cpp/proxy$ grep identifier  Noop.cpp.001t.tu | wc -l
1217

Note that I’ve added -fdump-translation-unit  to the CPPFLAGS in a Makefile.

Each change has a significant effect on the resultant file:

adam@frenzy:~/devel/cpp/proxy$ wc -l Noop.cpp.001t.tu
6853 Noop.cpp.001t.tu
adam@frenzy:~/devel/cpp/proxy$ wc -l xyzzy.cpp.001t.tu
6845 xyzzy.cpp.001t.tu
adam@frenzy:~/devel/cpp/proxy$ wc -l empty.cpp.001t.tu
6841 empty.cpp.001t.tu

Because the symbol gets added early (@4) it bumps all of the other symbols in the file up one, so a diff would take a little parsing.  A visual inspection quickly shows that the following section has been added to xyzzy.cpp.001t.tu

@3      var_decl         name: @4       type: @5       srcp: xyzzy.cpp:1
chan: @6       link: static   size: @7
algn: 32       used: 0
@4      identifier_node  strg: xyzzy    lngt: 5
@5      integer_type     name: @8       size: @7       algn: 32
prec: 32       sign: signed   min : @9
max : @10

If we compare the two files based on the @ signs:

adam@frenzy:~/devel/cpp/proxy$ grep — @ xyzzy.cpp.001t.tu | wc -l
4427
adam@frenzy:~/devel/cpp/proxy$ grep — @ empty.cpp.001t.tu | wc -l
4424

We can see we have added three, which corresponds with what we have above.

Just adding the emptyr struct adds 10 lines:

adam@frenzy:~/devel/cpp/proxy$ grep — @ Noop.cpp.001t.tu | wc -l
4434.

To make iut a little easier, I went in and put a carriage return after struct Noop{};  Now I can look for Noop.cpp:1 or Noop.cpp:2

This eems to be the set of lines added for struct Noop:

@6      type_decl        name: @11      type: @12      srcp: Noop.cpp:1
note: artificial              chan: @13
@7      integer_cst      type: @14      low : 32
@8      type_decl        name: @15      type: @5       srcp: <built-in>:0
note: artificial
@9      integer_cst      type: @5       high: -1       low : -2147483648
@10     integer_cst      type: @5       low : 2147483647
@11     identifier_node  strg: Noop     lngt: 4
@12     record_type      name: @6       size: @16      algn: 8
tag : struct   flds: @17      binf: @18

Let’s see what happens if we add field.

Here’s OneOp.cpp

struct OneOp{
int aaa;
};
static int xyzzy;

adam@frenzy:~/devel/cpp/proxy$ grep — @ Noop.cpp.001t.tu | wc -l
4434
adam@frenzy:~/devel/cpp/proxy$ grep — @ OneOp.cpp.001t.tu | wc -l
4439

We get another five lines.  Let’s see if this is linear.

adam@frenzy:~/devel/cpp/proxy$ grep — @ TwoOp.cpp.001t.tu | wc -l
4444

adam@frenzy:~/devel/cpp/proxy$ grep — @ ThreeOp.cpp.001t.tu | wc -l
4449

Let’s try a function now.

adam@frenzy:~/devel/cpp/proxy$ cat OneFunc.cpp
struct OneFunc{
int narf();
};
static int xyzzy;

adam@frenzy:~/devel/cpp/proxy$ grep — @ OneOp.cpp.001t.tu | wc -l
4439
adam@frenzy:~/devel/cpp/proxy$ grep — @ OneFunc.cpp.001t.tu | wc -l
4448

About double the info.

My next goal will be to diagram out the data structures we have here using UML.

Things look fairly straight forward in the decifering until we get to function_type.  There, we have a reference to retn which in this case happens to be a void, but could concievably be any of the data types.

I have long since abandonded this approach, but may pick it back up again some day, so I will publish this and let the great crawlers out there make it avaialble to some poor sap that wants to continue it.  If you do so, please let me know.

Proxies in C++

The Proxy design pattern and Aspect Oriented Programming have the common goal of extracting cross cutting concerns from code and encapsulating them.  A cross cutting concern usually happens on a function boundary:  check security, object creation and so on.  Proxies allow you to make an object that mimics the interface of the called object, but which provides additional functionality.

For an inversion of control container, object dependency and object creation may follow two different policies.  If Object A needs and Object of type B, that dependency should be initialized when object A is created.. However, if creating object B is expensive, and object B is not always needed, object B should be created on Demand.  This approach is called “Lazy Load” and it is one of the types of proxies that the Gang of Four book enumerates.

Java provides a mechanism to make a proxy on the fly. The use of the proxy object provides a function

public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable

Let’s define a C++ class as a pure abstract base class:

class Interface {
public:
virtual void action1(int i) = 0;
virtual void action2(int j) = 0;
}

And a class that implements that interface with some side effect.

class RealClass :public Interface {

int val;

public:

void action1(int i){val = i;}

void action2(int i){val = 333 * i;}

};

Then a Lazy Load Proxy would be defined like this:

typedef Interface* (* create_delegate_fn());

class LazyLoadProxy : public Interface  {
create_delegate_fn* fetcher;
Interface* delegate;
Interface* fetch(){
if (!delegate){
delegate = (*fetcher());
}
return delegate;
}
public:
LazyLoadProxy(create_delegate_fn create_delegate):
delegate(0)
{
fetcher = create_delegate;
};

virtual void action1(int i){
fetch()->action1(i);
};
virtual void action2(int j){
fetch()->action1(j);
};
}

This cannot be completely templatized, but a good portion of it can be abstracted away, leaving the compiler to check your work for the rest.   If we want to tie this into out inversion of control framework, we need to make sure that the create_delegate has access to the same Zone used to create the Proxy object.  Thus the Zone should be stored in a member variable of the Dynamic proxy.  We should really tie this into the resolver.h code from previous posts, and pass the Zone along to be stored the lazy load proxy.  It is also likely that you will want the lazy load proxy to own the delegated item, so you may want to add a virtual destructor to the interface (always a good idea), and then delete the delegate in the destructor of the proxy.  Here’s the templatized code:

#include <resolver.h>

template <typename T>  class LazyLoadProxy : public T  {
public:
typedef T* (*create_delegate_fn)(dependency::Zone&);

private:

T* (*fetcher)(dependency::Zone&);
T* delegate;
dependency::Zone& zone_;

protected:
T* fetch(){
if (!delegate){
delegate = (fetcher(zone_));
}
return delegate;
}
public:
LazyLoadProxy(dependency::Zone& zone,create_delegate_fn create_delegate):
zone_(zone),
delegate(0)
{
fetcher = create_delegate;
};

virtual ~LazyLoadProxy(){
if (delegate){
delete delegate;
}
}
};

And the code specific to creating and registering the Interface version of the LazyLoadProxy is:

class InterfaceLazy : public LazyLoadProxy<Interface>  {
public:
InterfaceLazy(dependency::Zone& zone, create_delegate_fn create_delegate):
LazyLoadProxy<Interface>(zone, create_delegate)
{
};

virtual void action1(int i){
fetch()->action1(i);
};
virtual void action2(int j){
fetch()->action1(j);
};
};

static Interface* createReal(dependency::Zone& zone){
return new RealClass;
}

static  Interface* createProxy(dependency::Zone& zone){
return new InterfaceLazy(zone, createReal);
}

DEPENDENCY_INITIALIZATION{
dependency::supply<Interface>::configure(0,createProxy);
return true;
}

Java dynamic proxies reduce the code for the proxy down to a singe function that gets executed for each method on the public interface, with the assumption that any delegation will be done via the reflection API.  C++ Does not have a reflection API, so we can’t take that approach.  If the C++ language were extended to allow the introspection of classes passed to a template, we could build a similar approach at compile time by providing a simple template function that gets expanded for each method of the abstract interface.

Dynamic proxies that are parameter agnositc are possible in C++, but are architecture specific, and depend on the parameter passing convetion.  I’m looking in to this, and will publish what I find in a future article.

Move to Red Hat

Sometimes you can’t tell where you are headed. But, after a while, if you look back, you realize that you have been headed in a straight line exactly where you want to go. Such is the case, I find, with my current acceptance of an offer of employment at Red Hat.

Very shortly, I will take a position as a senior software engineer at Red Hat, in Westford , MA. I am on the team responsible for, amongst other things, Red Hat Satellite Server. This pulls together several two trends in my career: Java, Linux, Systems Mangement, and JBoss.  I look forward to posting lessons learned from this new venture.

Duck Typing in C++

One common description of Object orient languages is that they use “Duck Typing.”  The idea is the if it looks lie a duck, walks like a duck, and sounds like a duck, you can treat it like a duck.  Java and C++ typically are set in opposition to Duck Typing:  You must have a complete Symbol match in order to be treated like a duck.

C++ is not Duck typed at run time, but it might be helpful to think in terms of Duck typing at compile time; Template programming is based on the Duck principal.  In C++, this is called the implied interface. A Template only cares that the type passed in as the typename has a member that matches the template.  The major difference here is that in Object Oriented Languages, this distinction is made at Run Time.  In C++, the distinction is made at Build time.

One rule of thumb that I have found useful in understanding the difference in approach between Java and C++ is this: Java assumes that Code will be reused without a recompile.  C++ Assumes that the compiler will be involved in a recompile.  Note that I say C++, and I mean Bjarne Stroustrup and the STL developers.  Not COM, CORBA or many of the Languages build in C++ but on top of the language. I’m not saying I approve or disapprove of this approach, just that it is a valuable way to think about the language.

Dependency Injection in C++

One goal of object oriented programming is to encapsulate functionality within a class.  If one class requires another in order to collaborate on a larger process, the programmer must deal with the wiring up of the two classes.  Much has been written about the correct way to do this in various object oriented languages.  The term “Inversion of Control” and the related concept of “Dependency Injection” have become part of the common language of software development, at least in the Java world, due to projects like Pico/Nano container, The Spring framework, and earlier efforts inside J2EE and ATG Dynamo.  These frameworks make use of the introspection mechanisms in Java to create instances of classes based on demand criteria.


Updated: links and using the code formatter. Changed Class from Single Letter to full names to be clearer and to not conflict with HTML tags.

Continue reading

C++ optimization for string16

Since wchar_t is 32 bits on Linux, I need to transform wstring to a different type in order to call the ODBC functions. The Windows code, on the other hand, can just use wstrings c_str() function to access the internal representation of the string. My goal is to minimize the code differences between platforms. On Linux, I will create a new class for string16 see earlier post). On Windows, I will just typedef wstring to string16. My hope then is to get the OS specific code down to the Linux implementation of string16, and to have the typedef optimize away the differences.

Here is a simplified version of the code that will be built and run on Windows:

typedef wstring& sqlstring;

void dothing(wstring s){
sqlstring sql(s);
wcout << sql << endl;
}

void doanother(wstring s){
wcout << s << endl;
}

And the result of building and disassembling using g++. Note that the code is the same. Hopefully Windos C++ complier will behave the same.

0000000000400ae0 <_Z9doanotherSbIwSt11char_traitsIwESaIwEE>:
400ae0: 48 83 ec 08 sub $0x8,%rsp
400ae4: 48 89 fe mov %rdi,%rsi
400ae7: bf c0 12 60 00 mov $0x6012c0,%edi
400aec: e8 07 fe ff ff callq 4008f8 <_ZStlsIwSt11char_traitsIwESaIwEERSt13basic_ostreamIT_T0_ES7_R
KSbIS4_S5_T1_E@plt>
400af1: 48 83 c4 08 add $0x8,%rsp
400af5: 48 89 c7 mov %rax,%rdi
400af8: e9 0b fe ff ff jmpq 400908 <_ZSt4endlIwSt11char_traitsIwEERSt13basic_ostreamIT_T0_ES6_@pl
t>
400afd: 90 nop
400afe: 66 90 xchg %ax,%ax

0000000000400b00 <_Z7dothingSbIwSt11char_traitsIwESaIwEE>:
400b00: 48 83 ec 08 sub $0x8,%rsp
400b04: 48 89 fe mov %rdi,%rsi
400b07: bf c0 12 60 00 mov $0x6012c0,%edi
400b0c: e8 e7 fd ff ff callq 4008f8 <_ZStlsIwSt11char_traitsIwESaIwEERSt13basic_ostreamIT_T0_ES7_R
KSbIS4_S5_T1_E@plt>
400b11: 48 83 c4 08 add $0x8,%rsp
400b15: 48 89 c7 mov %rax,%rdi
400b18: e9 eb fd ff ff jmpq 400908 <_ZSt4endlIwSt11char_traitsIwEERSt13basic_ostreamIT_T0_ES6_@pl
t>
400b1d: 90 nop
400b1e: 66 90 xchg %ax,%ax