How does Duff's device work?

前端 未结 11 1647
日久生厌
日久生厌 2020-11-22 04:56

I\'ve read the article on Wikipedia on the Duff\'s device, and I don\'t get it. I am really interested, but I\'ve read the explanation there a couple of times and I still do

11条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-22 05:36

    There are some good explanations elsewhere, but let me give it a try. (This is a lot easier on a whiteboard!) Here's the Wikipedia example with some notations.

    Let's say you're copying 20 bytes. The flow control of the program for the first pass is:

    int count;                        // Set to 20
    {
        int n = (count + 7) / 8;      // n is now 3.  (The "while" is going
                                      //              to be run three times.)
    
        switch (count % 8) {          // The remainder is 4 (20 modulo 8) so
                                      // jump to the case 4
    
        case 0:                       // [skipped]
                 do {                 // [skipped]
                     *to = *from++;   // [skipped]
        case 7:      *to = *from++;   // [skipped]
        case 6:      *to = *from++;   // [skipped]
        case 5:      *to = *from++;   // [skipped]
        case 4:      *to = *from++;   // Start here.  Copy 1 byte  (total 1)
        case 3:      *to = *from++;   // Copy 1 byte (total 2)
        case 2:      *to = *from++;   // Copy 1 byte (total 3)
        case 1:      *to = *from++;   // Copy 1 byte (total 4)
               } while (--n > 0);     // N = 3 Reduce N by 1, then jump up
                                      //       to the "do" if it's still
        }                             //        greater than 0 (and it is)
    }
    

    Now, start the second pass, we run just the indicated code:

    int count;                        //
    {
        int n = (count + 7) / 8;      //
                                      //
    
        switch (count % 8) {          //
                                      //
    
        case 0:                       //
                 do {                 // The while jumps to here.
                     *to = *from++;   // Copy 1 byte (total 5)
        case 7:      *to = *from++;   // Copy 1 byte (total 6)
        case 6:      *to = *from++;   // Copy 1 byte (total 7)
        case 5:      *to = *from++;   // Copy 1 byte (total 8)
        case 4:      *to = *from++;   // Copy 1 byte (total 9)
        case 3:      *to = *from++;   // Copy 1 byte (total 10)
        case 2:      *to = *from++;   // Copy 1 byte (total 11)
        case 1:      *to = *from++;   // Copy 1 byte (total 12)
               } while (--n > 0);     // N = 2 Reduce N by 1, then jump up
                                      //       to the "do" if it's still
        }                             //       greater than 0 (and it is)
    }
    

    Now, start the third pass:

    int count;                        //
    {
        int n = (count + 7) / 8;      //
                                      //
    
        switch (count % 8) {          //
                                      //
    
        case 0:                       //
                 do {                 // The while jumps to here.
                     *to = *from++;   // Copy 1 byte (total 13)
        case 7:      *to = *from++;   // Copy 1 byte (total 14)
        case 6:      *to = *from++;   // Copy 1 byte (total 15)
        case 5:      *to = *from++;   // Copy 1 byte (total 16)
        case 4:      *to = *from++;   // Copy 1 byte (total 17)
        case 3:      *to = *from++;   // Copy 1 byte (total 18)
        case 2:      *to = *from++;   // Copy 1 byte (total 19)
        case 1:      *to = *from++;   // Copy 1 byte (total 20)
               } while (--n > 0);     // N = 1  Reduce N by 1, then jump up
                                      //       to the "do" if it's still
        }                             //       greater than 0 (and it's not, so bail)
    }                                 // continue here...
    

    20 bytes are now copied.

    Note: The original Duff's Device (shown above) copied to an I/O device at the to address. Thus, it wasn't necessary to increment the pointer *to. When copying between two memory buffers you'd need to use *to++.

提交回复
热议问题