views:

414

answers:

6
void Send(int * to, const int* from, const int count)
{
    int n = (count+7) / 8;
    switch(count%8)
    {
       case 0: do { *to++ = *from++;
       case 7:      *to++ = *from++;
       case 6:      *to++ = *from++;
       case 5:      *to++ = *from++;
       case 4:      *to++ = *from++;
       case 3:      *to++ = *from++;
       case 2:      *to++ = *from++;
       case 1:      *to++ = *from++;
        } while (--n>0);
    }
}
+17  A: 

This is Duff's Device for copying memory buffers.

David Joyner
Link answers are bad!
Seth Illgard
@Seth why are link answers bad? I've never heard of Duff's Device before, and a link to its Wikipedia article was quite nice to find in the most up-voted answer.
Dave DeLong
+5  A: 

Read about Duff's Device

AndreyT
Please don't provide link answers
Seth Illgard
@Seth: Why not? The post linked to in both anwsers (AndreyT's and David Joyner's) were good descriptions, and are maintained. There's absolutely no reason to copy and paste all of that just to avoid a link. (And with 279 reputation points, perhaps you should be around a little longer before trying to be the post police?)
Ken White
A: 

The word you want to search for is Duff's Device. The real answer (to "what does it do?") is that it makes you look like an idiot for using obscure language misfeatures.

paul
Yikes. Play nice, man.
Jacob
Sorry...I should've said "if you actually use it". Wanting to understand what the deal is is perfectly reasonable.
paul
Every C/C++ programmer has to use Duff's Device in the real code at least once in their life. Duff's Device is full of strange perverted beauty. In a way, it is divine, like recursion.
AndreyT
+6  A: 

This mingling of a switch statement and a while loop is called "Duff's Device". It is a way to unroll loops, which was an optimization often used in earlier times.

So this code still copies the memory contents from one place to the other, but it might be more efficient. Beware, on today's architectures you should always measure that, because with cache locality and blindingly fast CPUs loop unrolling is often a bad idea.

Steffen
+2  A: 

Duff's device

In computer science, Duff's device is an optimized implementation of a serial copy that uses a technique widely applied in assembly language for loop unwinding. Its discovery is credited to Tom Duff in November of 1983, who at the time was working for Lucasfilm. It is perhaps the most dramatic use of case label fall-through in the C programming language to date. Duff does not claim credit for discovering the concept of loop unrolling, just this particular expression of it in C.

ephemient
+2  A: 

This is functionally identical to the code below:

for(int i=0;i<n;i++)
{
  *to++=*from++;
}

The difference is that your code unrolls the loop so that only 1 loop iteration is required for each 8 integers copied. Since there are no breaks for any of the cases, execution falls through from each case label to the next.

When count%8==0, 8 copies are executed inside of the loop for the first iteration

when count%8==7, 7 copies are executed for the first iteration

and so forth. After the first iteration with %8 copies, exactly 8 copies happen per iteration.

By unrolling the loop in this manner, the loop overhead is significantly reduced. It's important to note the order of the case values (0,7,6,5,4,3,2,1) which lend themselves to being translated into a jump table by the compiler.

update

An issue with the example code posted by OP is that a count value of 0 will cause 8 copies to take place, potentially resulting in a buffer overflow.

David Lively
Your explanation seems somewhat unclear. If I'm not mistaken, the switch is only for determining how many unrolled assignments to perform during the first iteration (to compensate that the buffer length might not be evenly divisible by 8).
UncleBens
That's correct. Sorry for the cloudy explanation.
David Lively