Archive for the ‘code snippet’ Category

Passing options in Ruby

Saturday, December 18th, 2010

A neat idiom for passing options to a class in Ruby …

class WithOptions
  def initialize(opts = {})
    @options = {
      :debug => false
    }.merge(opts)
  end
end
foo = WithOptions.new(:debug => true)

# or ...

other_opts = {
  :debug => true,
  :debug_level => :WARN
}
foo = WithOptions.new(other_opts)

Any options passed will be merged with the default options setup in the class. Options with the same name will override the default options. The same technique can be used with methods.

An alternative approach is to specify the defaults directly in the default options hash parameter.

def some_method(opts = {:debug => false})
  puts opts[:debug]
end

Demystifying the volatile keyword

Tuesday, May 13th, 2008

Following on from my earlier post about the restrict keyword, I’d like to try and dispell the myth around the volatile keyword. The meaning of volatile is a popular interview question, particularly for embedded development jobs and I’ve heard some programmers describe the properties of this keyword as if it had super powers.

The volatile keyword does a very simple job. When a variable is marked as volatile, the programmer is instructing the compiler not to cache this variable in a register but instead to read the value of the variable from memory each and every time the variable is used. That’s it – simple isn’t it?

To illustrate the use of the keyword, consider the following example:volatile int* vp = SOME_REGISTER_ADDRESS;
for(int i=0; i<100; i++)     foo(*vp);[/sourcecode] In this simple example, the pointer vp points to a volatile int. The value of this int is read from memory for each loop iteration. If volatile was not specified then it is likely that the compiler would generate optimized code which would read the value of the int once, temporarily store this in a register and then use the register copy during each iteration. Examples of where volatile is often used:

  • When accessing hardware registers via pointers. It is necessary for the generated code to always access the hardware registers value and never a potentially out of date copy.
  • When accessing a variable that is shared between two or more threads or between a thread and an ISR.

Common myths about the volatile keyword:

  • A volatile variable will never reside in cache memory – e.g. within the L2 cache of a processor. This is not true. In the case where the volatile variable is shared between two software threads, it is highly likely that the variable will exist in cached memory and the cache coherency policy will ensure that the threads will see the correct and up-to-date value of the variable in the event that the threads are running on seperate cores that don’t share the same cache. When the volatile variable refers to a hardware register, it is likely that the memory map of the system will be setup such that this register is not cacheable in the processor cache, but this is setup and managed by the appropriate device driver and is not something that is provided by the volatile keyword.

Thats’ it. So the next time you hear somebody waxing lyrical about the super powers of the volatile keyword, please feel empowered to enlighten them!

C99 restrict Keyword

Tuesday, May 13th, 2008

I was pleasently surprised to encounter a C keyword that I had never heard of before. The keyword in question is the restrict keyword which is a type qualifier for pointers and is a formal part of the C99 standard. This keyword allows programmers to declare that pointers which share the same type do not alias each other.  This information can then be used by the compiler to make optimizations when using the pointers. If the data is in fact aliased, the results are undefined.

Consider the following example:

memcpy((void* restrict) dst, (void* restrict) src, size);

 

This tells the compiler that neither the dst or src pointer paramters overlap and so the compiler is free to apply any optimizations – including optimizations that may result in out of order reads/writes.

Mainstream compilers have varying support for this feature.

  • GCC supports it in C99 mode  – specified via the “-std=c99” option or for non-C99 code by specifying __restrict to enable the keyword as a GCC extension.
  • Microsoft’s Visual Studio .NET 2005/2008 compiler doesn’t support this feature as specified in the C99 standard but does provide similar support using the __restrict specifier. Micorosft also allows this keyword to be specified for both C and C++ code. See the MSDN documentation for more details on Microsofts implementation and differences between it’s support and the C99 specification of restrict.

Finally, it should be noted that this keyword is specific to C and is not specified in the 1998 C++ specification nor is it currently planned for inclusion in the fothcoming C++ specification update.

References:

C++ Lambda Functions

Sunday, April 6th, 2008

A previous post showed a code snippet for dumping the contents of an STL container using an ostream_iterator. Things have now gotten a little bit easier with the introduction of lambda functions into the upcoming C++0x standard. Lambda functions allow pieces of code to be passed around as if they were ordinary objects. Applying lambda functions for dumping the contents of an STL container gives:

vector v(10);
generate(v.begin(), v.end(), rand);
for_each(v.begin(), v.end(),
    [](int& x){ cout << x << " "; }) [/sourcecode] OK, so the syntax looks a bit strange at first, but it does add a powerful construct to the language. Lambdas have only just been added to the C++0x standard and support for lambdas are not included in the beta version of the Visual Studio 2008 TR1 feature pack.

For more details and examples of lambda functions, check out Herb Sutter’s recent trip report from the February/March ISO C++ standards meeting.

C++ TR1: array VS 2008 Bug

Saturday, March 15th, 2008

Microsoft have recently released a Beta version of the Visual Studio 2008 Feature Pack which includes support for most of the C++ standard library extensions described in TR1. Alas, the beta sticker is appropriate as there are still some bugs to be ironed out.

The TR1 array container template provides functionality for implementing a fixed size array. This is a halfway point between plain old C style arrays and C++ STL vectors. The defining property of the array container is that its size is fixed. Consider and example of an array of 4 integers

array<int, 4> = { 0, 1, 2, 3 };

Since it adheres to the STL container rules, it must implement methods such as size(), and max_size(). For the array container, both of these should return the size of the array, which is fixed. In the above example, both should return 4. However, when using the VS 2008 TR1 implementation of array, a bug appears. The code:

#include
#include using namespace std;
using namespace std::tr1;

int main()
{
    array arr = {1, 2, 3, 4};
    cout << "size: " << arr.size() << endl;     cout << "max_size: " << arr.max_size() << endl;     return 0; }[/sourcecode]

Produces the output:

size: 4max_size: 1073741823

instead of:

size: 4max_size: 4

If we take a look at the implementation of max_size() we can see the problem

size_type max_size() const
{
    // return maximum possible length of sequence
    size_type _Count = (size_type)(-1) / sizeof(_Ty);
    return (0 < _Count ? _Count : 1); }[/sourcecode] Instead of simply retuning N (the size of the array), it performs the same computation as if this was a vector. This issue has been logged as a bug with Microsoft and will hopefully be fixed before the "Gold" release of the feature pack.

 
 
 
 
 

 

 

Simple container dump using STL iterator

Saturday, July 14th, 2007

Quick and dirty printing of containers contents in C++ using STL ostream_iterator …

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    vector<int> v(10);
    generate(v.begin(), v.end(), rand);
   
    copy(v.begin(), v.end(),
        ostream_iterator<int>(cout, "n"));

    return 0;
}