Can computers save the planet?

Computers and energy hungry, polluting to build and polluting to dispose of. They are an icon of the environment destroying technological society and deserve the derision they get from the green movement: Right? Maybe not.

All of the above computer criticisms have elements of truth, yet they miss what computers do to save the planet. That silent work is so complex and requires such specialist training to understand that neither it nor its impact gets discussed. Yet, if humanity is to prosper and the biosphere cope, computers are not only important, they are the key stone without which all our efforts will collapse.

Until last week I was driving a car built in 1994 which used an engine designed in the 1980s. With careful driving I could squeeze 35 miles out of one gallon (UK) of fuel. Last week I replaced my aging 1.8 petrol Citroen with a very modern (2005) 1.6 turbo diesel Peugeot. The newer car is considerably bigger than the old one and, due to air conditioning and air bags plus loads of other new features, considerable heavier as well. Not only that, the new engine produces nearly the same horsepower and over 1.5 times as much torque as it older one. However, with care I can manage to get 70 miles from a one gallon of fuel. Yes, the new car is twice as fuel efficient (the calorific values of diesel and gasoline being nearly identical).

"What has this got to do with computers?" one might ask. The beauty of this example lies in how on Earth such an efficient engine could have been built. The engine in question is a computer controlled, 16 value common rail turbo-charged diesel. Not only is there the rather obvious computer control system but the design and manufacture of every component is well beyond human ability without the aid of computers. Put simply, computers have allow me to halve my automotive fuel use and gain a benefit in comfort and safety!

To save our planet we pretty much have to consume less resource. To do so without culling humans, or destroying the technological society which so many of use want to or already have, will come down to efficiency. It is simply not proven that world cannot support everyone enjoying the lifestyle the rich world currently enjoys. We do not know if it can or it can not. We do know is that the world cannot support everyone consuming resource at the rate the richest people currently consume resource; that simply is not the same thing.

Computing technology has a proven, sterling track record of improving efficiency. Not just a little bit of improvement, but a huge, cumulative and non linear improvement. Computers have already yielded staggering efficiency gains in many human activities yet their use has only just begun to take hold. Rather than an icon of hatred, computers, computational technology and the computer industry should be seen as one of the most - if not the most - green in existence.

Will C++ Be Its Own Downfall

Sometimes the powerful and heavy can be taken down by the small and light weight.

My recent experience in C# and VB versa C++ lead to the (possibly sad) conclusion that C++ will force it self to become increasing marginalized in the new, highly parallel world of 21st century computing.

The premature announcement of programming language death seems to be a recurring theme over the last half century. I would like to learn from the mistakes of the past and not be condemned to repeat them; therefore, I am going to stick to 'marginalized'. C++ is a fabulous, wonderful, rich and powerful programming language. It has a nasty (and quite frankly deserved) reputation of being hard to learn and use. However, this is not the pressure I believe will increasingly marginalize it over the upcoming decades. That pressure is the rapidly changing architecture of modern computers compared to the 'naked to the machine' underpinnings of C++.

Garbage collection was the key the unlocked this concept for me. Memory management from 1980 through to around 2003 was easy. All one had to do was not cause leaks. This paradigm has been completely changed since the default architecture of all but the most trivial computers became parallel. The problem is not that C++ cannot 'do' garbage collection, the problem is quite the reverse. C++ forces the program to implement garbage collection. Languages which are based on .Net, the JVM or even archaic languages like FORTRAN and COBOL, simply never address the issue; the language implementation just gets on with collecting garbage in the background and the programmer gets on with creating code.

This 'taking away responsibility from the programmer' is often considered a weakness which leads the language to inevitably be of lower performance and less flexible. Whilst this argument has merit, reality is somewhat different. I suspect (and am finding out in practice) that getting C++ to perform as quickly as C# or Java (etc.) is increasing difficult. For example, my C++ version of VSPL runs five times slower in inner loops than the C# version. Yes, optimization will close the gap but - 5 to 1!

Software, and the languages in which it is written, exist in a complex context of human and technological interaction. To simply pretend this is not the case because we do not like it can prove a foolish 'head in the sand' approach. Again, to consider garbage collection, making a scalable, fast reliable garbage collector work on a multi-processor machine is really hard. In C++ fully isolating its implementation from the rest of the program is highly intrusive. This means 'in the real world' programming will be slower, more mistakes will be made and, when the garbage collection scheme is updated, some code will break. In languages which force these issues to be hidden, the garbage collector can be updated with relative impunity.

There are other such issues, like atomisity, non locking collections and sychronisation. All these can be isolated from the programmer in higher level languages, but require interaction with the programmer in C++. Yes, it is true that templates can hide these issues to some exent, but this is hiding behing a curtain. In C# or Java the hiding in behind an inpentrable wall. The difference to the long term stability of the code base is huge.

What does all this actually mean? It means Java, VB and C# programs will have longer lifetimes than C++ ones in many cases. Sooner or later, a really big program in C++ will get so clunky and far away from its original architecture that it will be rewritten. Whilst 'lighter weight' languages will allow their programs to keep going and evolving. C++ will remain useful for those bits of software which can afford to have vast resource thrown at them (like the implementation of the C# garbage collector) whilst the bulk of software will be written (or continue to be written) in C#/VB/Java/Fortran and COBOL, depending on its sphere of use.

Finally, what of C? This is a hard one to tell. C is not a very nice language. It is inflexible and overly simple. On the other hand C is a wonderful language. It is simple and powerful and very close to the machine. Somehow, this language seems to lie outside the scope of the discussion here. It will remain important because people like writing in it. Maybe I need tom give this issue another period of though, as C just does not fit into the model presented here!

Moving Job

It is time to move and take up new, exciting challenges!

Yep, at the end of this month (sept 2008) I will be leaving The Project Network. I have accepted a new position with Micro Focus as a Software Systems Developer, Senior Principle.

Moving on leaves me with mixed feelings. I could not be more excited about the new position and the excellent career opportunities, intellectual challenges and fascinating conversations with co-workers which lie ahead of me. However, over the last four years (nearly) The Project Network has been good to me and I will miss some of the friends I have made whilst working there.

Having said that -the marvels of email and sites like LinkedIn mean there is no excuse for loosing touch!

A Rose By An Other Name - YES IT WAS A COMMODITY BUBBLE

On this page there are images of two bubbles - one in soap and the other in oil!

The funny thing is that so many analysts went around saying that the commodity markets, especially oil, where not in a bubble. "The days of cheap energy are gone" and "$200 a barrel oil will be here soon". Yes - the fundamentals of oil mean it will increase slowly over then next decade as it is harder to come by and more of it is wanted and used. However, there is only one reasonable explanation for the rise up from ~$95 to ~$145 and back - a bubble. The credit crunch caused capital speculators to move out of buying and selling loans they did not care about to buying and selling oil they never intended to use.

Is there a lesson to be learned? Yes - don't listen to analysts!

Cultural Shift Ensures IT Move To Asia Is Long Term If Not Permanent

A recent survey indicates 6% of organisations plan repatriate IT positions. They will not be able to.

www.computerweekly.com:
A survey of firms by ReThink Recruitment has revealed that 6% of organisations plan to bring offshored IT work back to the UK over the next year.

The research also shows that 75% of IT departments have no plans to offshore any more IT work over the coming year only 19% of IT departments are contemplating further offshoring.

This is indicative of a rampant misunderstanding of the way IT is done. Non IT literate managerial practice sees developers and IT project managers as a commodity. Ideas like staff development, investment and loyalty have moved to downsizing, offshoring and cost base rationalisation. The result is that the supply of good, high level, IT staff in the UK is drying up. People are either leaving the industry or moving sideways into consulting positions. Both of these are one way trips. The former, because getting back to speed with the latest technology is near impossible once those skills have slipped; the latter because, once someone has adjusted their life style to consulting, the money is too hard to give up.

ReThink said that strong evidence was emerging that the offshoring rationale was beginning to unravel, as wage inflation in overseas IT centres eroded cost savings, and quality control and data security concerns became more important.

ReThink director Michael Bennett said, "For every three IT directors thinking about sending work offshore, there is one planning to repatriate jobs to the UK. That's quite a significant number, and clearly shows that offshoring is no longer a one-way street."

"A lot of organisations saw offshoring purely as a way to cut costs, but spiralling wage inflation in offshore locations, combined with the project management cost of coordinating teams across international time zones, can eat into any cost savings."

Again, this indicates naivety in extremis. The only reason that Asian costs seem high compared to UK costs is because of offshoring. When/if the attempt at job repatriation happens, there will be a massive hardening of the UK job market. Top end developer salaries have been stagnant since 9/11; that is due to change and putting pressure on the job market now will make Asia seem cheep all over again.

For what it is worth, here is my advice to both Asian and UK top level managers. Firstly to the UK: Relearn loyalty and staff development (some still do this – find them and learn from them); investment cycles longer than 12 months are the only way to build a stable IT worker base. Secondly to Asia: Your cost advantage is no longer set in stone; just like the UK learned in the 80s, productivity is key. But, do not forget the painful lesson the UK is learning now, never forget your staff need development!

(Even) More On Counted Pointers

This has been a HUGE learning curve for me as I have never implemented automatic garbage collection in C++ before. Here is another installment and a collector that no longer leaks memory (blush).

Also check out the VSPL/Language development index page.

FYI - the picture has absolutely nothing to do with this post other than it is about a pointer!

As I mentioned before, the garbage collector for my referrence VSPL/C++ implementation is just a reference counter. Actually, I say 'just' but reference counters are becoming a hot topic again. There are places where 'stop the world' garbage collection is not really the best approach. First of all, mark/scan garbage collection has to traverse the whole heap which can be expensive which very large programs and massive object counts. Also, games and real time applications cannot have 'stop the world' methodologies. So, despite the drawbacks, reference counting might prove to be the garbage collector of choice for many applications moving forward.

VSPL has been designed to be threaded from day one, this means its garbage collection needs to be thread safe. To achive this I implemented atomic operations for the reference increment and decrement. However, some operands in VSPL need to actually be reference counted even though they are still passed as VSPL_OPERAND counted pointer objects. These operand closely relate to constants in other languages; also there is no point counting null pointers. So, I implmeneted the ability for the counted pointer not to bother counting is it was in 'permanent' mode. Unfortunately, I made a simple mistake of still calling new for the counter memory its self, even though the counter pointer was not counting. This new memory was never reclaimed. A little bit of code fixed this and the approach works very cleanly now:

This leaks like a sive:
 :ptr(p), count(new VSPL_INT(1)),useCount(p!=0)
This does not:
 :ptr(p), count(p!=0?new VSPL_INT(1):0),useCount(p!=0)

Again...

Leaky:
 :ptr(p), count(new VSPL_INT(1)),useCount(!permanent)
Clean:
 :ptr(p), count(permanent?0:new VSPL_INT(1)),useCount(!permanent)

The next advance I've made is to have a tracing and non tracing version. The tracing version uses RTTI (run time type identification) to keep track of what counted pointers are in existance and to what objects they pointer. It keeps a separate track of the permanent and referece counted versions. This means that if memory appears to be leaking in the program you can define VSPL_MEMTRACE and recompile and then call DumpCReferences for counted references or DumpPReferences for permanent references to see what references are actually active. Here is an example of the output, first the counted reference system showing creating and deleting of objects.

Deleting->00339170 class VSPL::cVSPL_List
Creating->00339170 class VSPL::cVSPL_Number
Creating->0033A958 class VSPL::cVSPL_List
Deleting->0033B308 class VSPL::cVSPL_List
Deleting->0033B150 class VSPL::cVSPL_Number
Creating->0033A858 class VSPL::cVSPL_List
Deleting->0033A958 class VSPL::cVSPL_List
Creating->0033A958 class VSPL::cVSPL_List
Deleting->0033A858 class VSPL::cVSPL_List
Creating->0033B330 class VSPL::cVSPL_Number
Creating->0033B358 class VSPL::cVSPL_List
Deleting->0033A958 class VSPL::cVSPL_List
Deleting->00339170 class VSPL::cVSPL_Number
Deleting->0033A9E8 class VSPL::cVSPL_RunnerOperand
Creating->00339198 class VSPL::cVSPL_Number
Creating->0033B078 class VSPL::cVSPL_List
Deleting->0033B358 class VSPL::cVSPL_List
Creating->0033A858 class VSPL::cVSPL_Number

Next the dump of permanent and counted objects near the end of the execution of the program:

All known counted   references
00335360->class VSPL::cVSPL_Parser::cNothing
003353E8->class VSPL::cVSPL_Parser::cTrue
00335468->class VSPL::cVSPL_Parser::cFalse
003356E8->class VSPL::cVSPL_StdLib::cGt
00335788->class VSPL::cVSPL_StdLib::cSum
00335A08->class VSPL::cVSPL_StdLib::cDiff
00335BA0->class VSPL::cVSPL_StdLib::cQuot
00335D38->class VSPL::cVSPL_StdLib::cProd
00335ED0->class VSPL::cVSPL_StdLib::cTimer
00336068->class VSPL::cVSPL_ExtLib::cPrint
00336750->class VSPL::cVSPL_Parser::cPushAccumulator
003380F8->class VSPL::cVSPL_Parser::cPopAccumulator
00338418->class VSPL::cVSPL_Parser::cAppend
00338458->class VSPL::cVSPL_Parser::cGet
003384F8->class VSPL::cVSPL_Parser::cIf
00338778->class VSPL::cVSPL_Parser::cElse
00338910->class VSPL::cVSPL_Parser::cInvoke
00338AA8->class VSPL::cVSPL_Parser::cLoop
00338B48->class VSPL::cVSPL_Parser::cCall
00338DC8->class VSPL::cVSPL_Parser::cInterpret
00339230->class VSPL::cVSPL_Parser::cStore
00339528->class VSPL::cVSPL_Parser::cNumber
00339658->class VSPL::cVSPL_Parser::cRetrieve
003396B0->class VSPL::cVSPL_Parser::cStore
00339B48->class VSPL::cVSPL_Parser::cRetrieve
00339C58->class VSPL::cVSPL_Parser::cStore
00339E08->class VSPL::cVSPL_Parser::cNumber
0033A0B8->class VSPL::cVSPL_Runner
0033A5D8->class VSPL::cVSPL_Runner
0033ADD8->class VSPL::cVSPL_Parser::cNumber
All known permanent references
00336310->class VSPL::cVSPL_Bool
003380A8->class VSPL::cVSPL_Bool
003395C0->class VSPL::cVSPL_Number
00339BE8->class VSPL::cVSPL_Number
0033AE20->class VSPL::cVSPL_Number

The above was generated whilst running the following VSPL:

Timer !time 100 !count [ ?count,1>Diff !count,0>Gt ] Loop Timer,?time>Diff Print

Finally, here is the counted reference code. Notes:

  • VSPL_INT is just int on Win32
  • The tracing class has to cope with counted pointers being created static and so it must create its MAP containers when they are needed rather than in the class initializer. I was in a bit of a hurry (and it if only debug code) as I just assumed a boolean will start of false and used that to control creating the maps. C++ says uninitialized memory can have any value, but Windows (and Linux I think) zeros it (which is false in bool). Anyhow, oneday I will go look up a better method of handling this.
  • The RTTI spec only seems to say that the name() returns a null turminated byte string. So std::string(typeid(*(this->ptr)).name()) may or may not produce a string usable for tracing. I have just made the assumption that it will and so far it works on Windows. I am starting to think of making a Linux version if time permits.

/* The below is the start of a linux version which uses atomicity.h
to provide the atomic increment and decrement of the reference count.*/
//#define GPP_MEMORY_MODEL
#ifdef GPP_MEMORY_MODEL
inline VSPL_INT InterlockedIncrement(VSPL_INT* count)
{
 __atomic_add((_Atomic_word*)cout,1);
 return *count;
}

inline VSPL_INT InterlockedDecrement(VSPL_INT* count)
{
 __atomic_add((_Atomic_word*)cout,-1);
 return *count;
}
#endif

#ifdef VSPL_MEMTRACE

 /* This class stores the information required for memory tracing
  * and does the pretty print of the memory trace
  */
 class MemTracer
 {
 private:
     static bool isInit;
     static void Init()
     {
         // This works on Windows - no reason to suspect
         // it will work anywhere else!
         if(!isInit)
         {
             cReferences=new std::map<std::string,std::string>();
             pReferences=new std::map<std::string,std::string>();
             isInit=true;
         }
     }

     static std::map<std::string,std::string>* cReferences;
     static std::map<std::string,std::string>* pReferences;

 public:
     static void DumpCReferences()
     {
         Init();
         for
         (
             std::map<std::string,std::string>::iterator it=cReferences->begin();
             it!=cReferences->end();
             ++it
         )
         {
             std::cout << it->first << "->" << it->second << std::endl;
         }
     }
     static void DumpPReferences()
     {
         Init();
         for
         (
             std::map<std::string,std::string>::iterator it=pReferences->begin();
             it!=pReferences->end();
             ++it
         )
         {
             std::cout << it->first << "->" << it->second << std::endl;
         }
     }

     static void SetCReference(std::string& k,std::string& v)
     {
         Init();
         (*MemTracer::cReferences)[k]=v;
     }

     static void SetPReference(std::string& k,std::string& v)
     {
         Init();
         (*MemTracer::pReferences)[k]=v;
     }

     static void RemoveCReference(std::string& k)
     {
         std::map<std::string,std::string>::iterator it=MemTracer::cReferences->find(k);
         MemTracer::cReferences->erase(it);
     }

 };

 /* This is the tracing verion of the counted pointer */
 template <class T>
 class CountedPtr
 {
 private:
     // I have put this first to double ensure it is 32(or 64) bit
     // aligned for the memory barrier - this is the ref count for
     // this counted pointer
     VSPL_INT* count;
     // This points to what ever this pointer points to
     T* ptr;
     // This sets if the counting part of this pointer is disabled.
     // Having this set to false means that the ref count is not used
     // which is what we want if we _know_ an object never needs to
     // be garbage collected so the cost of thread safe ref counting
     // need not be incured.
     VSPL_BOOL useCount;


 public:

     // Note that quite often a counted reference is created and
     // then a value set to it with the = operator. This means that
     // this constructor will be called with p=0 (NULL) as default.
     // When this happens - there is no point reference counting a
     // pointer to null - so the useCount is then to FALSE when p=0
     // and true otherwise.
     explicit CountedPtr(T* p=0)
         :ptr(p), count(p!=0?new VSPL_INT(1):0),useCount(p!=0)
     {
         if(useCount)
         {
             std::cout << "Creating->" << this->ptr << " " << typeid(*(this->ptr)).name() << std::endl;
             MemTracer::SetCReference(ToString(this->ptr),std::string(typeid(*(this->ptr)).name()));
         }
         else
         {
             if(p!=0)
             MemTracer::SetPReference(ToString(this->ptr),std::string(typeid(*(this->ptr)).name()));
         }
     }

     CountedPtr(T* p,VSPL_BOOL permanent)
         :ptr(p), count(permanent?0:new VSPL_INT(1)),useCount(!permanent)
     {
         if(useCount)
         {
             std::cout << "Creating->" << this->ptr << " " << typeid(this->ptr).name() << std::endl;
             MemTracer::SetCReference(ToString(this->ptr),std::string(typeid(*(this->ptr)).name()));
         }
         else
         {
             if(p!=0)
             MemTracer::SetPReference(ToString(this->ptr),std::string(typeid(*(this->ptr)).name()));
         }
     }

     CountedPtr(const CountedPtr<T>& p) throw()
         :    ptr(p.ptr),count(p.count),useCount(p.useCount)
     {
         if(useCount)
         {
             InterlockedIncrement(count);
         }
     }

     ~CountedPtr() throw()
     {
         dispose();
     }

     CountedPtr<T>& operator=(const CountedPtr<T>& p) throw()
     {
         if(this != &p){
             dispose();
             ptr=p.ptr;
             count=p.count;
             useCount=p.useCount;
             if(useCount)
             {
                 InterlockedIncrement(count);
             }
         }
         return *this;
     }

     T& operator*() const throw()
     {
         return *ptr;
     }

     T* operator->() const throw()
     {
         return ptr;
     }

     VSPL_BOOL IsNull()
     { return ptr==0; }

private:
     void dispose()
     {
         if(useCount)
         {
             if(InterlockedDecrement(count) == 0)
             {
                 std::cout << "Deleting->" << this->ptr << " " << typeid(*(this->ptr)).name()  << std::endl;
                 MemTracer::RemoveCReference(ToString(this->ptr));
                 delete count;
                 delete ptr;
             }
         }
     }
 };
#else

 /* The non tracing version for normal operations.
  * This is infinitely faster, never use the tracing
  * version unless you are debuging for leaks!
  */
 template <class T>
 class CountedPtr
 {
 private:
     VSPL_INT* count;
     T* ptr;
     VSPL_BOOL useCount;
 public:
     explicit CountedPtr(T* p=0)
         :ptr(p), count(p!=0?new VSPL_INT(1):0),useCount(p!=0){}

     CountedPtr(T* p,VSPL_BOOL permanent)
         :ptr(p), count(permanent?0:new VSPL_INT(1)),useCount(!permanent){}

     CountedPtr(const CountedPtr<T>& p) throw()
         :    ptr(p.ptr),count(p.count),useCount(p.useCount)
     {if(useCount)InterlockedIncrement(count);}

     ~CountedPtr() throw()
     {dispose();}

     CountedPtr<T>& operator=(const CountedPtr<T>& p) throw()
     {
         if(this != &p){
             dispose();
             ptr=p.ptr;
             count=p.count;
             useCount=p.useCount;
             if(useCount) InterlockedIncrement(count);
         }
         return *this;
     }

     T& operator*() const throw()
     {return *ptr;}

     T* operator->() const throw()
     {return ptr;}

     VSPL_BOOL IsNull()
     { return ptr==0; }

 private:
     void dispose()
     {
         if(useCount)
         {
             if(InterlockedDecrement(count) == 0)
             {
                 delete count;
                 delete ptr;
             }
         }
     }
 };
#endif

Reference Counting Garbage Collection And Virtual Destructors

I goofed! Is you use reference counting with down casting, you must make the destructors virtual - DOH!

Also check out the VSPL/Language development index page.

In my previous post you might have noticed the deliberate mistake?

 class iVSPL_Operand
 {  
 public:
  virtual VSPL_STRING ToString()       const = 0;

  virtual VSPL_STRING GetDescription() const = 0;
 };
 typedef CountedPtr<Operand> VSPL_OPERAND;

 class iVSPL_Operator
 {
 public:
  virtual VSPL_STRING Word()                            const = 0;

  virtual VSPL_OPERAND Interpret(VSPL_OPERAND,cVSPL_Context&) = 0;
 };
 typedef CountedPtr<Operator> VSPL_OPERATOR;

The pure virtual interface classes here do not have virtual destructors. This means that when the reference count hits zero, VSPL_OPERATOR VSPL_OPERAND will call the destructor to the base class not the derived class. Therefore, any clean up (memory reclamation etc) simply will not happen!

Here is my simple fix:

 class iVSPL_Operand
 {  
 public:
  virtual VSPL_STRING ToString()       const = 0;

  virtual VSPL_STRING GetDescription() const = 0;

  virtual ~iVSPL_Operand(){}
 };
 typedef CountedPtr<Operand> VSPL_OPERAND;

 class iVSPL_Operator
 {
 public:
  virtual VSPL_STRING Word()                            const = 0;

  virtual VSPL_OPERAND Interpret(VSPL_OPERAND,cVSPL_Context&) = 0;

  virtual ~iVSPL_Operator(){}
 };
 typedef CountedPtr<Operator> VSPL_OPERATOR;

This way the derived classes do not have to implement a destructor, but if they do, it will get called!

Creating New Operators In VSPL

vspl logo
VSPL - So simple an amoeba can understand it!

One key design goal of VSPL is to make it easy to extend and embed. To do that - it has to be easy to add functionality to the language. VSPL chains operators and operands, so extending means adding operators and maybe operands. Here is how to add operators in the C# and C++ versions.

Also check out the VSPL/Language development index page.
  1. Introduction and implementation in C#
  2. The C++ implementation

Introduction and implementation in C#

Life in C# is easier than in C++ for VSPL. The reason being that the operands in VSPL/C# are just C# objects. All objects in C# are children of object. What is more, C# implements auto-boxing so even native types like int and double can be treaded as objects (when you do C# automatically wraps them in a 'box' that then implements the object interface). So, implementing new functionality in VSPL/C# is just a matter of writing objects which implement VSPL.iVSPL_Operator (which used to be called iVSPL_Interpretable but has been changed to be uniform with the VSPL/C++):

namespace VSPL
{
    interface iVSPL_Operator
    {
        string Word
        {
            get;
        }
        object Interpret(object input, cVSPL_Context context);
    }
}

Below is the cut down but fully working version of the ExtLib (extension library) in VSPL/C#. I have wrapped the whole implementation in a static class. I like this way of doing things are it give a good control over access to static functions and private or public inner classes. However, the use of a static wrapper class in not required - it is just a programming style.

The next thing to notice is public static void Install(cVSPL_Parser parser). This is called by the code which runs the VSPL parser. It adds operators to VSPL via the AddKeyWord method of the parser. A program can have any number of different parser objects and each one can have a different range of operators added to it; the adding of operators other than the core (which make it Turin complete) is all implemented at runtime.

Next we have the inner class example. Again, this does not need to be an inner class - I just did it this way. This class implements the iVSPL_Operator interface. The iVSPL_Operator.Word method is called by the parser to discover the operator token. In this case it is ADO.Connect which means that the parser will be able to then read the following code:

"My connect string" ADO.Connect !myDBConnection

The parser will recognize ADO.Connect and map that to a cADOConnect object. The runner will then invoke the object iVSPL_Operator.Interpret(object input, cVSPL_Context context) method on the operator object when the VSPL is running. This method has two arguments, the input which is the passed forward object and the context. The context hold the accumulator (which creats lists with the , and > operators) and the store. Interaction with the context is for more VSPL internal activities like thread calls and function calls; I shall describe these features in another post.

Finally the object iVSPL_Operator.Interpret(object input, cVSPL_Context context) method must return a VSPL operand. As I mentioned, in VSPL/C# operands are just C# objects so this method must return an object or null. In this case it returns the database connection. It is also worth noting the cVSPL_Runner which invokes VSPL catches the C# exception base class and so if object iVSPL_Operator.Interpret(object input, cVSPL_Context context) throws an exception, VSPL can handle it gracefully.

using System.Data.SqlClient;

namespace VSPL
{
    static class cVSPL_ExtLib
    {
        public static void Install(cVSPL_Parser parser)
        {
            parser.AddKeyWord(new cPrint());
        }

        public class cADOConnect : VSPL.iVSPL_Operator
        {
            string iVSPL_Operator.Word
            {
                get { return "ADO.Connect"; }
            }

            object iVSPL_Operator.Interpret(object input, cVSPL_Context context)
            {
                SqlConnection con = new SqlConnection(input.ToString());
                con.Open();
                return con;
            }
        }
    }
}

The C++ implementation

A I mentioned in a previous post, VSPL/C++ was more tricky to implement because the notion of operators and operands in VSPL simply requires automatic garbage collection. In my C++ implementation of VSPL I have used a simple, thread safe reference counting pointer template implementation. The template is the used to create counted pointers for iVSPL_Operand and iVSPL_Operator. These are then typedef to VSPL_OPERAND and VSPL_OPERATOR. These two replace the built in handle based object passing and garbage collection that C# uses.


 class iVSPL_Operand
 {
  
 public:
  virtual VSPL_STRING ToString()       const = 0;

  virtual VSPL_STRING GetDescription() const = 0;
 };
 typedef CountedPtr<iVSPL_Operand> VSPL_OPERAND;

 class iVSPL_Operator
 {
 public:
  virtual VSPL_STRING Word()                            const = 0;
  virtual VSPL_OPERAND Interpret(VSPL_OPERAND,cVSPL_Context&) = 0;
 };
 typedef CountedPtr<iVSPL_Operator> VSPL_OPERATOR;

Once you have the concept of VSPL_OPERAND and VSPL_OPERATOR in place, the C++ code reads just like the C#. Here is the implementation of the Print operator in VSPL (which is in ExtLib as it has operating system interaction). This is VC++ code.

namespace VSPL
{
 void cVSPL_ExtLib::Install(cVSPL_Parser& parser)
 {
  parser.AddKeyWord(VSPL::VSPL_OPERATOR(new cPrint()));
 }

 //class cPrint
 VSPL_STRING cVSPL_ExtLib::cPrint::Word() const
 {
  return L"Print";
 }

 VSPL_OPERAND cVSPL_ExtLib::cPrint::Interpret(VSPL_OPERAND input,cVSPL_Context& context)
 {
  std::cout << narrowString(input->ToString()) << std::endl;
  return input;
 }
}

One this to notice is that VSPL uses wide strings. This means that the return L"Print"; in te Word method actually causes the creation of a VSPL_STRING which is just a typedef for std:wstring. Similarly, the input->ToString() produces a VSPL_STRING which must be narrowed to be output to the console (on Windows).

A GOOD DAY: C++ VSPL works and meeting first class people

Today has been a fabulous day. I had a great meeting with some very interesting people this morning. What is the best way to unwind? Naturally, write some code :)

Also check out the VSPL/Language development index page.

Here is a very simple bit of VSPL code called from C++. This VSPL implementation is pure C++, not a wrapper around the C# or something which - as I will explain later - is why I took a few afternoons to get it to work...

int _tmain(int argc, _TCHAR* argv[])
{
 //runnerTest();
 VSPL::cVSPL_Parser parser;
 VSPL::cVSPL_StdLib::Install(parser);
 VSPL::cVSPL_ExtLib::Install(parser);
 VSPL::VSPL_OPERATOR op=parser.Parse(L"\"Hello World\" Print 12.3 Print False Print 2,1>Gt Print 1,-1>Sum Print ,1>Gt Print 1,-1>Gt Print",L"No File");
 VSPL::cVSPL_Runner* r=dynamic_cast(&*op);
 r->Invoke();
}

The issue I hit was garbage. Really - I had not realized just quite how totally dependant on the managed code garbage collector the vb/c#/java implementations really were. You see, VSPL is really a series of operators that pass operands between them. Both the operators and the operands are objects and they are created and destroyed based on the state of the executing VSPL code. So, a simple (which is what it is supposed to be) implementation of VSPL really has to have some sort of automatic reclamation of operands and operators when they are no longer used. (The reason for reclaiming operators is that VSPL code blocks are first class and so need to be creatable and automatically reclaimed on being discarded).

As I have already discussed, I used counted pointers with atomic reference update to manage garbage collections. There is an issue - cycles will not be collected; however, I am not sure that VSPL is going to get used for the sort of thing that might cause cycles much - I am not too worried about that for now.

So finally I am going to discuss what this means:

 VSPL::cVSPL_Runner* r=dynamic_cast(&*op);
 r->Invoke();
Where the parser has parsed a string and produced an invokable VSPL code block which comes wrapped in the runner object. The snag is that the parser has to output something which is garbage collected - so it outputs a VSPL_OPERATOR. VSPL_OPERATOR is a counted pointer compiled to count iVSPL_Operator objects. Invoke is not on iVSPL_Operator, it is on the child class cVSPL_Runner, so I cannot use the counted pointer directly. Dynamic casting &*op fixes this. The unary * operator is actually calling a operator method which returns a reference to the object which is being pointed to. Then the & indirects it again as a raw pointer which dynamic_cast can actually work on to get to the child class methods.

Whilst all this is not new or particularly cleaver, it did take a bit of time to get all that was need working and have a productive framework in which to develop C++ VSPL. I think developing the 'C#' like way of managing operator and operand objects has taken me at least as long as porting the code once the framework was in place.

OK - that is all for now :)

OMG - Firefox browser share THRASHES IE for First Time

Another three months on from my last report and the world has turned upside down! Firefox and IE have simply swapped places as IE becomes the second most popular browser.

Looking at the two reports below (June-top and Sept-bottom 2008) you could be forgiven for thinking they are identical. But Firefox and IE have simply swapped with Firefox grabbing nearly half of all hits (49.34%) whilst IE is now in a firm second place (41.04%).

May-June 2008 browser visits to Nerds-Central
Aug-Sept 2008 browser visits to Nerds-Central

Other interesting trends are an ever increasing number of different platforms (including mobile) and the appearance of Chrome (the Google browser). Whilst Nerds-Central is a highly technophilic website, the trend in these results must indicate a seismic shift in the world of browsers. Further, this shift from IE to Firefox is not due to IE users shunning Nerds-Central, the actual hit count form IE has dropped only slightly from 4780 to 4,661.

Nerds Central First Poll Closed

There was a good mix, but Excel/VBScript is most popular with Open Source/Linux a strong second.

A Try At Thread Safe Counted Pointers In C++

vspl logo VSPL - So simple an amoeba can understand it!

Whilst VSPL may (or may not) be simple, getting C++ to perform reference counting garbage collection in a multi-threaded environment - efficiently - does not seem to be. Here are some of my ideas so far.

Also check out the VSPL/Language development index page.

As part of my research into VSPL I am writing a C++ implementation. This s much more challenging than the C# (or vb.net or Java) versions because I need to figure out what to do for memory management. Specifically, how to keep track of and reclaim VSPL operands.

The single most important aim of VSPL is to be simple. As such, the memory model used for VSPL should be simple; simple to understand and simple to implement. A full blown 'stop the world' garbage collector is not simple so I discounted that. However, part of VSPL is crying out for garbage collection. To see this, we can consider the following code:

1,1>Sum

The tokens are '1' ',' '1' '>' and 'Sum'. These tokens are translated into objects and the objects invoked in order the output of one the input to the next. One can see these tokens as operators and the values passed between them as operands. The operators in VSPL are stored in code blocks. The destructor of a code block can destroy all the operators and so normal C++ new/delete and stack semantics will do just fine. However, the operands are created by the VSPL code execution and so normal C++ semantics will have no way of managing them. However, once and operand is no longer referenced directly, or via some container, to the VSPL context, and operator or the pass forward object, it must be reclaimed or memory will leak.

The solution I am working with for now is smart counted pointers. These are dead simple - ish. The idea is to make a object with holds a pointer to the operand whilst overloading the * and -> c++ operators so it can be used like a regular pointer. Copy constructer semanitics and overloading the c++ = operator then alow this object to count the number of pointers which exist and point to the vspl operator. When instance count of the smart pointer for a given vspl operator hits zero (in the last destructor) the vspl operator is destroyed.

If only life was that simple

This is all great until you hit modern computer architectures. With hyperthreading and multi-core, everything must work on SMP. This means that the counted smart pointers in VSPL must work on SMP. Consider a vspl operand pointed to by smart pointers in different threads. Those threads may be running on different cores. Execution and memory access re-ordering mean that access to the count from one thread may be out of order with that from another. In other words, you cannot assume that (if(--*count==0){/* delete here */} will work as one thread might be creating a new smart pointer and the write increaing the counter simply not be visible 'yet' to the thread running the test. The solution is to create a memory barrier before the update that forces atomicity. On windowns, this can be done with InterlockedDecrement and InterlockedIncrement. The linux kernel appears to have smb_wmb,smb_rmb and smb_mb to help with this sort of thing, but I am still trying to work out how to do this in linux user space.

Is this the complete story. Well, no. The snag is that all this memory barrier and synchronisation stuff slows down the counting. And this counting is pretty much core to VSPL so optimization would be nice! Going back to the code above, both the '1' operators pass forward a cVSPL_Number object; what is more to the point, they always pass forward the same cVSPL_Number object. Therefore, this objects reclamation can be done from the operator and not the garbage collector. The optimization here is that some operands do not need to be reference counted.

I considered two ways of implementing this 'turn off the counter' approach. One was to use polymorphism of the smart counted point class and the other was to use some logic in the object. I chose the latter because the polymorphism would prevent compiler optimizations of the polymorphic methods (or might). In all honestly, I doubt it makes much difference either way.

Anyhow - here is the work in progress smart counted thread safe pointer class in the Windows code base:

/* MS Specific as long is 32 bytes on Windows
* check as will break reference counter (at least)
* is different on different platform
*/
typedef long         VSPL_INT;
typedef double       VSPL_NUMBER;
typedef bool         VSPL_BOOL;
typedef std::wstring VSPL_STRING;

/* This is the CountedPtr template class from
* the C++ Standard Library - Nicolai M. Josutti 2001.
*
* I have altered it to do reference counting behind a memory
* barrier using InterlockedIncrement and InterlockedDecrement.
*
* This is Windows VC++ specific. If you are trying to port to a
* different OS/Compiler/Architecture then you should implement
* or find an implementation for atomic addition and take it from
* there.
*
* Search for 'linux atomic operations' for example. Also for linux
* see atomicity.h which seems to be getting better at this
* sort of thing in 2.5+ kernels.
*
* The impact on my test machine of using interlockedIncreament over
* simple ++ is somewhere between 2 and 4 times - not too bad.  If
* any serious code ran between pointer allocations and deletion this
* would mean the interlock made nearly no difference to actual
* performance.
*/
template <class T>
class CountedPtr
{
private:
   // I have put this first to double ensure it is 32(or 64) bit
   // aligned for the memory barrier - this is the ref count for
   // this counted pointer
   VSPL_INT* count;
   // This points to what ever this pointer points to
   T* ptr;
   // This sets if the counting part of this pointer is disabled.
   // Having this set to false means that the ref count is not used
   // which is what we want if we _know_ an object never needs to
   // be garbage collected so the cost of thread safe ref counting
   // need not be incured.
   VSPL_BOOL useCount;

public:

   // Note that quite often a counted reference is created and
   // then a value set to it with the = operator. This means that
   // this constructor will be called with p=0 (NULL) as default.
   // When this happens - there is no point reference counting a
   // pointer to null - so the useCount is then to FALSE when p=0
   // and true otherwise.
   explicit CountedPtr(T* p=0)
       :ptr(p), count(new VSPL_INT(1)),useCount(p!=0)
   {
#ifdef VSPL_MEMTRACE
       if(useCount)
       {
           std::cout << "Create counted   reference->" << this->ptr << std::endl;
       }
       else
       {
           std::cout << "Create permanent reference->" << this->ptr << std::endl;
       }
#endif
   }

   CountedPtr(T* p,VSPL_BOOL permanent)
       :ptr(p), count(new VSPL_INT(1)),useCount(!permanent)
   {
#ifdef VSPL_MEMTRACE
       if(useCount)
       {
           std::cout << "Create counted   reference->" << this->ptr << std::endl;
       }
       else
       {
           std::cout << "Create permanent reference->" << this->ptr << std::endl;
       }
#endif
   }

   CountedPtr(const CountedPtr<T>& p) throw()
       :    ptr(p.ptr),count(p.count),useCount(p.useCount)
   {
       if(useCount)
       {
           InterlockedIncrement(count);
#ifdef VSPL_MEMTRACE
           std::cout << "Add counted   reference->" << this->ptr << std::endl;
#endif
       }
#ifdef VSPL_MEMTRACE
       else
       {
           std::cout << "Add permanent reference" << this->ptr << std::endl;
       }
#endif
   }

   ~CountedPtr() throw()
   {
       dispose();
   }

   CountedPtr<T>& operator=(const CountedPtr<T>& p) throw()
   {
       if(this != &p){
           dispose();
           ptr=p.ptr;
           count=p.count;
           useCount=p.useCount;
           if(useCount)
           {
               InterlockedIncrement(count);
           }
#ifdef VSPL_MEMTRACE
       std::cout << "Reference = copy->" << this->ptr << std::endl;
#endif
       }
       return *this;
   }

   T& operator*() const throw()
   {
       return *ptr;
   }

   T* operator->() const throw()
   {
       return ptr;
   }

private:
   void dispose()
   {
#ifdef VSPL_MEMTRACE
       std::cout << "Reference disposing->" << this->ptr << std::endl;
#endif
       if(useCount)
       {
           if(InterlockedDecrement(count) == 0)
           {
               delete count;
               delete ptr;
#ifdef VSPL_MEMTRACE
               std::cout << "Reference  disposed->" << this->ptr << std::endl;
#endif
           }
       }
#ifdef VSPL_MEMTRACE
       else
       {
           std::cout << "Reference permanent->" << this->ptr << std::endl;
       }
#endif
   }
};