C语言简单数据缓存实现

来源:互联网 发布:淘宝签证代办 编辑:程序博客网 时间:2024/04/30 01:58
  1. /**
  2. example: How to easily Cache in C.
  3. Author: suxiaojack
  4. Date:2008.12
  5. Licence:No Limited.
  6. 看看Lua源代码的test中一段代码:
  7. fib.lua
  8. -----------
  9. -- fibonacci function with cache
  10. -- very inefficient fibonacci function
  11. function fib(n)
  12.         N=N+1
  13.         if n<2 then
  14.                 return n
  15.         else
  16.                 return fib(n-1)+fib(n-2)
  17.         end
  18. end
  19. -- a general-purpose value cache
  20. function cache(f)
  21.         local c={}
  22.         return function (x)
  23.                 local y=c[x]
  24.                 if not y then
  25.                         y=f(x)
  26.                         c[x]=y
  27.                 end
  28.                 return y
  29.         end
  30. end
  31. -- run and time it
  32. function test(s,f)
  33.         N=0
  34.         local c=os.clock()
  35.         local v=f(n)
  36.         local t=os.clock()-c
  37.         print(s,n,v,t,N)
  38. end
  39. n=arg[1] or 24                -- for other values, do lua fib.lua XX
  40. n=tonumber(n)
  41. print("","n","value","time","evals")
  42. test("plain",fib)
  43. fib=cache(fib)
  44. test("cached",fib)
  45. -----------
  46. **********************************
  47. 实在是太漂亮了!不修改原函数的情况下,动态修改替换,完成了缓存数据的工作。
  48. javascript等其他有些动态语言也可以做到,这种解析。
  49. 其调用过程实质如何?
  50. 原本有个fib
  51. 后来返回一个修改过的匿名函数给fib,假如名为fib_patch
  52. 调用fib实际调用的是
  53.    (see fib) | (hide fib)
  54. fib_patch<<--->>fib
  55. 有交叉的!!
  56. ***********************************
  57. 利用C可以直接实现返回一个函数吗?
  58. 返回一个函数指针是可以的。但是无法简单做到修改原函数过程来回调新函数。
  59. 除非使用汇编硬编码,太麻烦了还不通用!!
  60. 为什么要用cache?无非是为查表提高递归效率。
  61. 为什么要保持原函数?无非是想使用原函数设计时的算法,而不重新写自带Cache的算法。
  62. 只有退而求其次,在少量修改原函数,保持算法形式不变的情况下,实现Cache添加。
  63. 看看正文:
  64. **/
  65. #include <stdio.h>
  66. #include <stdlib.h>
  67. #include <string.h>
  68. //NIL must be nicety
  69. #define NIL (-1)
  70. #define CACHESIZE 1024
  71. #define CacheProc(name) name_patch
  72. #define Cache(name) name_cache
  73. #define InitCacheFor(name) memset(name_cache,NIL,CACHESIZE*sizeof(int))
  74. #define GEN_CACHE_PROC(name)/
  75.         int Cache(name)[CACHESIZE];/
  76.         int CacheProc(name)(int n)/
  77.         {/
  78.                 if(Cache(name)[n]==NIL)/
  79.                 {/
  80.                         Cache(name)[n]=name(n);/
  81.                 };/
  82.                 return Cache(name)[n];/
  83.         }
  84. int fib(int);
  85. int fib2(int);
  86. int CacheProc(fib2)(int);
  87. int fib(int n)
  88. {
  89.         if (n<=2)return 1;
  90.         else
  91.                 return fib(n-2)+fib(n-1);
  92. }
  93. /**
  94. to keep form as fib
  95. just need to call CacheProc
  96. 保持算法形式上和fib一样
  97. **/
  98. int fib2(int n)
  99. {
  100.         printf("fib2 be called:%d/n",n);
  101.         if (n<=2)return 1;
  102.         else
  103.                 return CacheProc(fib2)(n-2)+CacheProc(fib2)(n-1);
  104. }
  105. /** to creat
  106. int Cache(fib2)[CACHESIZE];
  107. int CacheProc(fib2)(int n)
  108. {
  109.         if(Cache(fib2)[n]==NIL)
  110.         {
  111.                 Cache(fib2)[n]=fib2(n);
  112.         };
  113.         return Cache(fib2)[n];
  114. }
  115. use GEN_CACHE_PROC**/
  116. GEN_CACHE_PROC(fib2);
  117. //
  118. int main()
  119. {
  120.     InitCacheFor(fib2);
  121.         while(1)
  122.         {
  123.                 int N;
  124.                 printf("intput N (<=0 exit):");
  125.                 if(scanf("%d",&N)==1)
  126.                 {
  127.             if(N>=1)
  128.             {
  129.                 printf("fib(%d)=%d/n",N,fib(N));
  130.                 printf("cached fib2(%d)=%d/n",N,fib2(N));
  131.             }else
  132.             {
  133.                 exit(0);
  134.             };
  135.                 }else
  136.                 {
  137.                     char bad[1024];
  138.             scanf("%s",bad);
  139.                 }
  140.         };
  141.         return 0;
  142. }
  143. /**
  144. 由上面可见,如果C的预处理提供给用户获取旧源码的接口,抒写C会更方便。
  145. 比如能获取fib函数的内容。让用户再次修改内容重定义。
  146. 当然,这个预处理工具C没有提供,但是自己添加一个动态patch文件工具
  147. 是比较容易的。(对原代码文件做修改,并生成新文件的工具)
  148. **/

 

 

 

原创粉丝点击