Frequently Asked Questions

General Questions:

  • Are you alive?

    Err... yes. I certainly hope so, at least.

  • Is GUF alive?

    GUF will live as long as I do.

  • Why do you never update the news page or release new versions of GUF?

    I'm too busy coding. :)

  • What is GUF?

    GUF is a general-purpose object-oriented framework library written in C++ and licensed under the GNU Library General Public Liscense (aka the "Lesser" General Public Liscense, though I object to that name).

  • What is a framework library?

    A framework library is a set of program modules that make it easier to write large-scale software. GUF is a general-purpose library, meaning that it is intended to be useful in any sort of software. However, the focus is on large-scale applications; small and simple programs are unlikely to benifit from using GUF.

  • Can I make commercial software with GUF?

    Sure. GUF is licensed under the GNU Library/Lesser General Public License (LPGL). You can write a program using GUF and sell it without paying any royalties or fees of any kind. Your can license your application under any license you wish. If you make any changes to GUF itself, however, you must distribute the source code for these changes licensed under the terms of the LGPL. See the file "COPYING" in the source package for more info.

  • Why are you doing all this work for free?

    If GUF were not free (by any or both definitions of the word), who would use it? Although GUF has many uses, its greatest strength will come when (and if) it is widely used. Then, people will write libraries with GUF that will be trivial to integrate, saving work and making large-scale software much easier to write. If GUF were not free, this would be nearly impossible, as only people with money would have access to it, and only non-free software would use it.

    Put simply, my goal is to improve software for everyone, not to make money for myself.

Technical Questions:

  • GUF looks a lot like Java. What's wrong with Java?

    GUF may look like Java on the surface, because on the surface it is very similar. Things like automatic memory management and new keywords like "synchronized", "interface", "implements", etc. may make it appear that GUF is just Java in C++.

    The similarities end there. GUF aims to be used in very different types of software than Java does. GUF is for large-scale projects, whereas Java is ideal for applets and the like. Sure, you can use Java in a large application, but you may run into problems.

    Personally, I can't use Java because it does not support pass-by-value objects. Take, for example, a 3D game engine (one of which I happen to be writing). 3D graphics involves lots of vector math, so we would like to create a 3D vector class which covers this stuff for us. Then, we would often like to create an array of vectors to describe a model. These arrays often contain on the order of ten thousand vectors. In Java, that would mean creating ten thousand separate vector objects, each with its own mutex and all the other data Java attaches to objects. Furthermore, you'd have an array of ten thousand pointers pointing at these objects. This is an extreme waste of memory and CPU power.

    Java also has the problem that it tends to encourage muli-threading rather than event-driven programming. For more on event-driven design, see the goals section.

    Of course, then there are all the arguments about efficiency of bytecode, interpreters, JIT compilers, etc. Whether they are valid or not, I'm sure I don't need to repeat them here.

  • GUF uses reference counting for memory management. Why not use full-scale garbage collection?

    While this is a very debatable topic, I believe that reference counting is better than full-scale garbage collection (GC).

    GC is unpredictable. GC algorithms usually need to make passes over the program's memory space at periodic intervals, looking for garbage memory that can be de-allocated. This requires pausing all threads of the program unexpectedly and often for long periods of time. Furthermore, this means that memory which is no longer needed stays allocated until the GC pass is made. Often, programs have to rely on an object's desctructor being called at a particular time. Because they can't do so using GC, some classes are instead forced to provide their destructors as member functions, which clients of the class have to manually call. This is worse than manual memory management, which GC is supposed to replace.

    Worse yet, GC can't be implemented reliably in C++. A garbage collector in a C or C++ program is forced to assume that all memory contains nothing but pointers, unless that memory is explicitly declared to contain something else. The result is that non-pointer data which coincidentally looks like pointers pointing at various data blocks will cause those blocks to never be deleted. A GC program which loads several megabytes of random data into RAM could effectively disable the garbage collector all together without realizing it!

    Thus, GC is only possible in languages designed for it. Other languages have other problems, however, and GUF will remain a C++ library.

  • But reference counting doesn't catch circular links! What do you do about that?

    Put simply, any program in which circular links appear is poorly designed. If you have two objects that can call each other, you are already putting yourself in more risk than you may realize. For example, if object A calls object B, and B then calls back A, the second call to A may be made while A is in an inconsistent state -- just like if two separate threads tried to access A at the same time. Additionally, in multithreaded systems, improperly managed circular links could lead to the risk of deadlock, where two threads are stuck waiting for each other to do something. In a properly designed system with no circular links, this risk is greatly reduced, if not removed all together.

    Of course, sometimes an object needs to be able to call back its owner without waiting for the owner to call it. GUF provides a simple way to do this: events. The owner of an object can ask that object to fire a particular event when it needs attention. The owner then responds to that event by calling whatever methods of that object it needs. No circular links necessary!

  • I heard that reference counting was slow. Is this true?

    It depends on your definition of slow. Sure, passing around a reference-counted pointer is slower than passing one that isn't, as the former requires an atomic increment and decrement, while the latter is just a copy. The question is, is this extra time relevant?

    The answer is most certainly no. When deciding if an operation takes too much time, you can't just look at the operation itself. You must look at it in context; you must take an example program, and see how much time that program spends performing that operation. In my case, I tested GAUGE^3D, a 3D graphics engine. I clocked GAUGE performing over 15,000 reference count operations per second -- much more than most programs would. Yet, it spent far less that 1% of its time performing these operations. Is reference counting worth a 1% performance drain? Personally, I would gladly sacrifice as much as 50% of my performance to be able to use reference counting, so a 1% drain means nothing at all to me.

    Furthermore, if you do not use reference counting, you have to use some other method of memory management. These take time too.