Duff's device实际上就是用循环展开的方式来提高程序效率的办法,循环展开可以有效利用CPU资源提升效率,当然我们也可以不借助它,可以分两步走,第一步展开,第二步计算剩下部分,但是代码不简洁,通用性也没有这个强。
下面介绍下Duff's device,假定要copy 20 个字节
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) }
#define DUFF_DEVICE_8(aCount, aAction) \ do { \ int count_ = (aCount); \ int times_ = (count_ + 7) >> 3; \ switch (count_ & 7){ \ case 0: do { aAction; \ case 7: aAction; \ case 6: aAction; \ case 5: aAction; \ case 4: aAction; \ case 3: aAction; \ case 2: aAction; \ case 1: aAction; \ } while (--times_ > 0); \ } \ } while (0)
int CopyToEEPROM(const void* pSource, void* pDest, unsigned len) { // Anything to copy? if (len > 0) { const char* s = (const char*)pSource; char* d = (char*)pDest; // First, need to copy data to page buffer DUFF_DEVICE_8(len, *d++ = *s++); // Start EEPROM write cycle HAL_EEPROM_WRITE(); // Check if data was transferred correctly s = (const char*)pSource; d = (char*)pDest; DUFF_DEVICE_8(len, if (*d++ != *s++) return 1; /* Fail */); } return 0; // Success }
http://www.drdobbs.com/a-reusable-duff-device/184406208