CnObjectPool.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnObjectPool;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:不可视工具组件包
  24. * 单元名称:可扩展的高性能的对象池单元
  25. * 单元作者:Chinbo(Shenloqi)
  26. * 备 注:
  27. * 开发平台:PWin2000Pro + Delphi 7.0
  28. * 兼容测试:PWin9X/2000/XP + Delphi 5/6
  29. * 本 地 化:该单元中的字符串暂不符合本地化处理方式
  30. * 单元标识:$Id$
  31. * 修改记录:2004.03.18 V1.0
  32. * 创建单元
  33. * 2004.09.18 V1.1
  34. * 增加属性WaitTimeOut,实现等待超时
  35. * (timeSetEvent实现,或许开销比较大,默认不打开)
  36. * 为Wrapper增加了CanReuse
  37. * 真正实现处于互斥和需要初始化状态的对象不被重用
  38. * 增加了Warpper的Info属性
  39. * 修改了ReleaseOne的实现,以便子类不需要强制类型转换
  40. * 2004.10.18 V1.2
  41. * 如果用户既没有设定ObjectClass也没有实现OnCreateOne则DoCreateOne会返回失败
  42. * 限制了同时设置ObjectClass和OnCreateOne
  43. * 第一次创建的对象默认设置为需要初始化
  44. ================================================================================
  45. |</PRE>}
  46. interface
  47. {$I CnPack.inc}
  48. uses
  49. Windows, Messages, SysUtils, Classes,
  50. CnConsts, CnClasses, CnCompConsts;
  51. type
  52. { 获取池对象的选项
  53. goNone 无任何特殊处理
  54. goReInit 需要初始化,不允许多次引用
  55. goMutex 不需要初始化,不允许多次引用
  56. }
  57. TCnObjectPoolGetOption = (goNone, goReInit, goMutex);
  58. { 释放池对象的选项
  59. roNone 仅仅减少引用计数
  60. roReInit 要求重新初始化
  61. roDelete 从对象池中删除对象
  62. roFree 释放该对象
  63. }
  64. TCnObjectPoolReleaseOption = (roNone, roReInit, roDelete, roFree);
  65. { 获取池对象的结果
  66. grSuccess 成功
  67. grReuse 多次引用的对象
  68. grInitFail 初始化失败
  69. grGetFail 获取失败
  70. grGetError 获取的结果有误
  71. grWaitFail 等待超时
  72. }
  73. TCnObjectPoolGetResult = (grSuccess, grReuse, grReinitFail, grGetFail, grGetError, grWaitFail);
  74. { 池中无空闲对象时的策略
  75. (如果对象需要被初始化或互斥则必须使用计数为0的对象)
  76. bpWait 等待空闲的对象
  77. bpGetFail 直接返回失败
  78. bpReuse 多次引用对象
  79. }
  80. TCnObjectPoolBusyPolicy = (bpWait, bpGetFail, bpReuse);
  81. { 池中对象都达到引用最大值时的策略
  82. bpWait 等待空闲的对象
  83. bpGetFail 直接返回失败
  84. }
  85. TCnObjectPoolPeakPolicy = bpWait..bpGetFail;
  86. { 获取池对象的策略
  87. gpReuse 使用引用计数最小的对象
  88. gpReuseMaxWorEff 引用计数最小的工作效率(平均工作时间)最高的
  89. gpReuseMinWorkCount 引用计数最小的工作次数最少的
  90. gpReuseMaxWorkCount 引用计数最小的工作次数最多的
  91. gpReuseMinWorkTime 引用计数最小的工作时间最少的
  92. gpReuseMaxWorkTime 引用计数最小的工作时间最多的
  93. gpMaxWorEff 工作效率最高的(无引用高于有引用)
  94. gpMinWorkCount 工作次数最少的(无引用高于有引用)
  95. gpMaxWorkCount 工作次数最多的(无引用高于有引用)
  96. gpMinWorkTime 工作时间最少的(无引用高于有引用)
  97. gpMaxWorkTime 工作时间最多的(无引用高于有引用)
  98. }
  99. TCnObjectPoolGetPolicy = (gpReuse,
  100. gpReuseMaxWorkEff,
  101. gpReuseMinWorkCount, gpReuseMaxWorkCount,
  102. gpReuseMinWorkTime, gpReuseMaxWorkTime,
  103. gpMaxWorkEff,
  104. gpMinWorkCount, gpMaxWorkCount,
  105. gpMinWorkTime, gpMaxWorkTime);
  106. TCriticalSection = class
  107. protected
  108. FSection: TRTLCriticalSection;
  109. public
  110. constructor Create;
  111. destructor Destroy; override;
  112. procedure Enter;
  113. procedure Leave;
  114. function TryEnter: Boolean;
  115. end;
  116. TCnCustomObjectPool = class; // forward
  117. { TCnObjectWrapper }
  118. TCnObjectWrapper = class(TObject)
  119. private
  120. FNeedReInit: Boolean; // 是否需要重新初始化,需要重新初始化的对象在计数为0前不可重用
  121. FCanReuse: Boolean; //是否能重用
  122. FRefCount: Integer; // 引用计数
  123. FWorkCount: Cardinal; // 工作次数
  124. FWorkTime: Cardinal; // 工作时间
  125. FObject: TObject; // 封装的对象
  126. FList: TList; // 保存TickCount
  127. FOwner: TCnCustomObjectPool;
  128. cs: TCriticalSection;
  129. function GetObject: TObject;
  130. procedure SetNeedReInit(const Value: Boolean);
  131. procedure SetObject(const Value: TObject);
  132. function GetNeedReInit: Boolean;
  133. function GetCanReuse: Boolean;
  134. procedure SetCanReuse(const Value: Boolean);
  135. procedure SetOwner(const Value: TCnCustomObjectPool);
  136. protected
  137. function GetInfo: string; virtual;
  138. procedure IncRef; virtual;
  139. procedure DecRef; virtual;
  140. property NeedReInit: Boolean read GetNeedReInit write SetNeedReInit;
  141. property CanReuse: Boolean read GetCanReuse write SetCanReuse; //当前对象是否能重用
  142. public
  143. constructor Create(AOwner: TCnCustomObjectPool); virtual;
  144. destructor Destroy; override;
  145. function RefCount: Integer;
  146. function WorkCount: Cardinal;
  147. function WorkTime: Cardinal;
  148. function WorkEff: Double;
  149. property ObjectWrapped: TObject read GetObject;
  150. property Info: string read GetInfo;
  151. end;
  152. TCnObjectWrapperClass = class of TCnObjectWrapper;
  153. { TCnCustomObjectPool }
  154. TOPEvent = procedure (Pool: TCnCustomObjectPool;
  155. Wrapper: TCnObjectWrapper;
  156. var Obj: TObject;
  157. var bSuccess: Boolean) of object;
  158. TCnCustomObjectPool = class(TCnComponent)
  159. private
  160. FObjectList: TList;
  161. hRelease, hTerminate: THandle;
  162. bTerminated: Boolean;
  163. FMinSize: Integer;
  164. FMaxSize: Integer;
  165. FPeakCount: Integer;
  166. FLowLoadCount: Integer;
  167. FWaitTimeOut: Integer;
  168. FPolicyOnBusy: TCnObjectPoolBusyPolicy;
  169. FPolicyOnGet: TCnObjectPoolGetPolicy;
  170. FPolicyOnPeak: TCnObjectPoolPeakPolicy;
  171. FObjectWrapperClass: TCnObjectWrapperClass;
  172. FOnReleaseOne: TOPEvent;
  173. FOnCreateOne: TOPEvent;
  174. FOnFreeOne: TOPEvent;
  175. FOnGetOne: TOPEvent;
  176. FOnReInitOne: TOPEvent;
  177. FObjectClass: TClass;
  178. function GetCount: Integer;
  179. procedure SetMinSize(const Value: Integer);
  180. procedure SetObjectClass(const Value: TClass);
  181. procedure SetPeakCount(const Value: Integer);
  182. procedure SetLowLoadCount(const Value: Integer);
  183. procedure SetOnCreateOne(const Value: TOPEvent);
  184. protected
  185. csObjectMgr: TCriticalSection;
  186. constructor CreateSpecial(AOwner: TComponent;
  187. AObjectWrapperClass: TCnObjectWrapperClass); virtual;
  188. procedure CreateBaseCountObjects(const bSetEvent: Boolean);
  189. function CanIncObject: Boolean; virtual;
  190. function IncObject(const bSetEvent: Boolean): TCnObjectWrapper; virtual;
  191. procedure DecObject(ObjWrapper: TCnObjectWrapper); virtual;
  192. function AddObjWrapper(ObjWrapper: TCnObjectWrapper): Boolean;
  193. function RemoveObjWrapper(ObjWrapper: TCnObjectWrapper): Boolean;
  194. function DoCreateOne(Wrapper: TCnObjectWrapper;
  195. var Obj: TObject): Boolean; virtual;
  196. function DoFreeOne(Wrapper: TCnObjectWrapper;
  197. var Obj: TObject): Boolean; virtual;
  198. function DoGetOne(Wrapper: TCnObjectWrapper;
  199. var Obj: TObject): Boolean; virtual;
  200. function DoReleaseOne(Wrapper: TCnObjectWrapper;
  201. var Obj: TObject): Boolean; virtual;
  202. function DoReInitOne(Wrapper: TCnObjectWrapper;
  203. var Obj: TObject): Boolean; virtual;
  204. function GetOne(var Obj: TObject;
  205. const go: TCnObjectPoolGetOption): TCnObjectPoolGetResult; virtual;
  206. procedure ReleaseOne(var Obj;
  207. const ro: TCnObjectPoolReleaseOption); virtual;
  208. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  209. property MinSize: Integer read FMinSize write SetMinSize;
  210. property MaxSize: Integer read FMaxSize write FMaxSize;
  211. property LowLoadCount: Integer read FLowLoadCount write SetLowLoadCount;
  212. property PeakCount: Integer read FPeakCount write SetPeakCount;
  213. property ObjectClass: TClass read FObjectClass write SetObjectClass;
  214. property ObjectWrapperClass: TCnObjectWrapperClass read FObjectWrapperClass;
  215. property PolicyOnBusy: TCnObjectPoolBusyPolicy
  216. read FPolicyOnBusy
  217. write FPolicyOnBusy default bpReuse;
  218. property PolicyOnPeak: TCnObjectPoolPeakPolicy
  219. read FPolicyOnPeak
  220. write FPolicyOnPeak default bpWait;
  221. property PolicyOnGet: TCnObjectPoolGetPolicy
  222. read FPolicyOnGet
  223. write FPolicyOnGet default gpReuse;
  224. property WaitTimeOut: Integer read FWaitTimeOut write FWaitTimeOut;
  225. property OnCreateOne: TOPEvent read FOnCreateOne write SetOnCreateOne;
  226. property OnFreeOne: TOPEvent read FOnFreeOne write FOnFreeOne;
  227. property OnGetOne: TOPEvent read FOnGetOne write FOnGetOne;
  228. property OnReleaseOne: TOPEvent read FOnReleaseOne write FOnReleaseOne;
  229. property OnReInitOne: TOPEvent read FOnReInitOne write FOnReInitOne;
  230. public
  231. constructor Create(AOwner: TComponent); override;
  232. destructor Destroy; override;
  233. function GetInfo: string; virtual;
  234. procedure ReInitAll;
  235. property Count: Integer read GetCount;
  236. end;
  237. { TCnObjectPool }
  238. TCnObjectPool = class(TCnCustomObjectPool)
  239. protected
  240. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  241. public
  242. constructor CreateSpecial(AOwner: TComponent;
  243. AObjectWrapperClass: TCnObjectWrapperClass); override;
  244. function GetObject(var Obj: TObject;
  245. const go: TCnObjectPoolGetOption = goNone): TCnObjectPoolGetResult;
  246. procedure ReleaseObject(var Obj;
  247. const ro: TCnObjectPoolReleaseOption = roNone);
  248. property ObjectClass;
  249. property ObjectWrapperClass;
  250. published
  251. property MinSize;
  252. property MaxSize;
  253. property LowLoadCount;
  254. property PeakCount;
  255. property PolicyOnBusy;
  256. property PolicyOnPeak;
  257. property PolicyOnGet;
  258. property OnCreateOne;
  259. property OnFreeOne;
  260. property OnGetOne;
  261. property OnReleaseOne;
  262. property OnReInitOne;
  263. end;
  264. implementation
  265. uses
  266. CnCommon,
  267. MMSystem; //timeSetEvent在该单元声明
  268. const
  269. MaxCardinal = High(Cardinal);
  270. { TCriticalSection }
  271. constructor TCriticalSection.Create;
  272. begin
  273. inherited;
  274. InitializeCriticalSection(FSection)
  275. end;
  276. destructor TCriticalSection.Destroy;
  277. begin
  278. DeleteCriticalSection(FSection);
  279. inherited;
  280. end;
  281. procedure TCriticalSection.Enter;
  282. begin
  283. EnterCriticalSection(FSection)
  284. end;
  285. procedure TCriticalSection.Leave;
  286. begin
  287. LeaveCriticalSection(FSection)
  288. end;
  289. function TCriticalSection.TryEnter: Boolean;
  290. begin
  291. Result := TryEnterCriticalSection(FSection)
  292. end;
  293. { TCnObjectWrapper }
  294. constructor TCnObjectWrapper.Create(AOwner: TCnCustomObjectPool);
  295. begin
  296. FOwner := AOwner;
  297. FNeedReInit := False;
  298. FCanReuse := True;
  299. FRefCount := 0;
  300. FWorkCount := 0;
  301. FWorkTime := 0;
  302. cs := TCriticalSection.Create;
  303. FList := TList.Create;
  304. if Assigned(AOwner) then
  305. AOwner.AddObjWrapper(Self);
  306. end;
  307. procedure TCnObjectWrapper.DecRef;
  308. var
  309. lcard: Cardinal;
  310. begin
  311. lcard := GetTickCount;
  312. cs.Enter;
  313. try
  314. if FRefCount > 0 then
  315. Dec(FRefCount);
  316. if FWorkCount < MaxCardinal then
  317. Inc(FWorkCount);
  318. if FList.Count > 0 then
  319. begin
  320. lcard := lcard - Cardinal(FList.Items[0]);
  321. FList.Delete(0);
  322. if MaxCardinal - FWorkTime > lcard then
  323. FWorkTime := FWorkTime + lcard
  324. else
  325. FWorkTime := MaxCardinal;
  326. end;
  327. finally
  328. cs.Leave;
  329. end;
  330. end;
  331. destructor TCnObjectWrapper.Destroy;
  332. begin
  333. if Assigned(FOwner) then
  334. FOwner.RemoveObjWrapper(Self);
  335. FList.Free;
  336. cs.Free;
  337. inherited;
  338. end;
  339. function TCnObjectWrapper.GetCanReuse: Boolean;
  340. begin
  341. cs.Enter;
  342. try
  343. Result := FCanReuse and (not FNeedReInit);
  344. finally
  345. cs.Leave;
  346. end;
  347. end;
  348. function TCnObjectWrapper.GetInfo: string;
  349. begin
  350. Result := 'Too busy to get info.';
  351. if cs.TryEnter then
  352. try
  353. Result := 'RefCount=' + IntToStr(FRefCount) +
  354. '; WorkCount=' + IntToStr(FWorkCount) +
  355. '; WorkTime=' + IntToStr(FWorkTime) +
  356. 'ms; WorkEff=' + IntToStr(Trunc(WorkEff)) +
  357. '; NeedReInit= ' + BoolToStr(FNeedReInit, True) +
  358. '; CanReUse= ' + BoolToStr(CanReuse, True) +
  359. '; Obj=' + IntToHex(Cardinal(FObject), 8);
  360. finally
  361. cs.Leave;
  362. end;
  363. end;
  364. function TCnObjectWrapper.GetNeedReInit: Boolean;
  365. begin
  366. Result := FNeedReInit;
  367. end;
  368. function TCnObjectWrapper.GetObject: TObject;
  369. begin
  370. Result := FObject;
  371. end;
  372. procedure TCnObjectWrapper.IncRef;
  373. begin
  374. cs.Enter;
  375. try
  376. Inc(FRefCount);
  377. FList.Add(Pointer(GetTickCount));
  378. finally
  379. cs.Leave;
  380. end;
  381. end;
  382. function TCnObjectWrapper.RefCount: Integer;
  383. begin
  384. Result := FRefCount;
  385. end;
  386. procedure TCnObjectWrapper.SetCanReuse(const Value: Boolean);
  387. begin
  388. cs.Enter;
  389. try
  390. FCanReuse := Value;
  391. finally
  392. cs.Leave;
  393. end;
  394. end;
  395. procedure TCnObjectWrapper.SetNeedReInit(const Value: Boolean);
  396. begin
  397. cs.Enter;
  398. try
  399. FNeedReInit := Value;
  400. finally
  401. cs.Leave;
  402. end;
  403. end;
  404. procedure TCnObjectWrapper.SetObject(const Value: TObject);
  405. begin
  406. cs.Enter;
  407. try
  408. FObject := Value;
  409. finally
  410. cs.Leave;
  411. end;
  412. end;
  413. procedure TCnObjectWrapper.SetOwner(const Value: TCnCustomObjectPool);
  414. begin
  415. cs.Enter;
  416. try
  417. FOwner := Value;
  418. finally
  419. cs.Leave;
  420. end;
  421. end;
  422. function TCnObjectWrapper.WorkCount: Cardinal;
  423. begin
  424. Result := FWorkCount;
  425. end;
  426. function TCnObjectWrapper.WorkEff: Double;
  427. begin
  428. cs.Enter;
  429. try
  430. if (FWorkTime = 0) or (FWorkCount = 0) then
  431. Result := 0
  432. else
  433. Result := FWorkTime / FWorkCount;
  434. finally
  435. cs.Leave;
  436. end;
  437. end;
  438. function TCnObjectWrapper.WorkTime: Cardinal;
  439. begin
  440. Result := FWorkTime;
  441. end;
  442. { TCnCustomObjectPool }
  443. function TCnCustomObjectPool.AddObjWrapper(
  444. ObjWrapper: TCnObjectWrapper): Boolean;
  445. begin
  446. csObjectMgr.Enter;
  447. try
  448. Result := FObjectList.IndexOf(ObjWrapper) < 0;
  449. if Result then
  450. FObjectList.Add(ObjWrapper);
  451. finally
  452. csObjectMgr.Leave;
  453. end;
  454. end;
  455. constructor TCnCustomObjectPool.Create(AOwner: TComponent);
  456. begin
  457. inherited;
  458. hRelease := CreateEvent(nil, True, False, nil);
  459. hTerminate := CreateEvent(nil, True, False, nil);
  460. if (hRelease = 0) or (hTerminate = 0) then
  461. raise Exception.Create('Cannot create events.');
  462. csObjectMgr := TCriticalSection.Create;
  463. FObjectList := TList.Create;
  464. bTerminated := False;
  465. FMinSize := 0;
  466. FMaxSize := 0;
  467. FPeakCount := 0;
  468. FLowLoadCount := 0;
  469. FPolicyOnBusy := bpReuse;
  470. FPolicyOnPeak := bpWait;
  471. FPolicyOnGet := gpReuse;
  472. FWaitTimeOut := 0;
  473. FObjectClass := nil;
  474. if FObjectWrapperClass = nil then
  475. FObjectWrapperClass := TCnObjectWrapper;
  476. //CreateBaseCountObjects(False);
  477. end;
  478. procedure TCnCustomObjectPool.CreateBaseCountObjects(const bSetEvent: Boolean);
  479. var
  480. i, iCount: Integer;
  481. begin
  482. if csDesigning in ComponentState then
  483. Exit;
  484. csObjectMgr.Enter;
  485. try
  486. iCount := FObjectList.Count;
  487. for i := iCount + 1 to FMinSize do
  488. IncObject(bSetEvent);
  489. finally
  490. csObjectMgr.Leave;
  491. end;
  492. end;
  493. constructor TCnCustomObjectPool.CreateSpecial(AOwner: TComponent;
  494. AObjectWrapperClass: TCnObjectWrapperClass);
  495. begin
  496. FObjectWrapperClass := AObjectWrapperClass;
  497. Create(AOwner);
  498. end;
  499. procedure TCnCustomObjectPool.DecObject(ObjWrapper: TCnObjectWrapper);
  500. begin
  501. csObjectMgr.Enter;
  502. try
  503. if not DoFreeOne(ObjWrapper, ObjWrapper.FObject) then
  504. begin
  505. if Assigned(ObjWrapper.FObject) then
  506. try
  507. ObjWrapper.FObject.Free;
  508. except
  509. end;
  510. end;
  511. try
  512. ObjWrapper.Free;
  513. except
  514. end;
  515. finally
  516. csObjectMgr.Leave;
  517. end;
  518. end;
  519. destructor TCnCustomObjectPool.Destroy;
  520. var
  521. i, iCount: Integer;
  522. begin
  523. bTerminated := True;
  524. SetEvent(hTerminate);
  525. csObjectMgr.Enter;
  526. try
  527. iCount := FObjectList.Count;
  528. for i := iCount - 1 downto 0 do
  529. begin
  530. DecObject(TCnObjectWrapper(FObjectList.Items[i]));
  531. end;
  532. FObjectList.Free;
  533. finally
  534. csObjectMgr.Leave;
  535. end;
  536. csObjectMgr.Free;
  537. CloseHandle(hTerminate);
  538. CloseHandle(hRelease);
  539. inherited;
  540. end;
  541. function TCnCustomObjectPool.DoCreateOne(Wrapper: TCnObjectWrapper;
  542. var Obj: TObject): Boolean;
  543. var
  544. tmpObj: TObject;
  545. begin
  546. csObjectMgr.Enter;
  547. try
  548. Result := False;
  549. if (not Assigned(Obj)) and
  550. Assigned(FObjectClass) then
  551. //因为很多对象不直接使用Create创建,所以这种最原始的创建是不推荐的
  552. //而且有的组件不允许直接调用Create,甚至有可能发生异常,所以使用了try...except...end;
  553. try
  554. tmpObj := FObjectClass.Create;
  555. Obj := tmpObj;
  556. except
  557. end;
  558. //如果用户既没有设置ObjectClass又没有实现OnCreateOne,则DoCreateOne会返回失败
  559. //虽然已经阻止了OnCreateOne和ObjectClass的共同设置,
  560. //但是如果用户既实现了OnCreateOne又设置了ObjectClass,则会内存泄露,
  561. //为了防止内存泄露,则释放因为设定了ObjectClass而自动创建的那个对象
  562. Result := Assigned(Obj) or Assigned(FOnCreateOne);
  563. if Assigned(FOnCreateOne) then
  564. begin
  565. tmpObj := nil;
  566. OnCreateOne(Self, Wrapper, tmpObj, Result);
  567. if Assigned(tmpObj) then
  568. begin
  569. //因为如TXMLDocument之类的组件如果没有设置Owner,则Free会出错,所以使用了try...except...end;
  570. try
  571. if Assigned(Obj) then
  572. Obj.Free;
  573. except
  574. end;
  575. Obj := tmpObj;
  576. end;
  577. end;
  578. if Result then
  579. begin
  580. Wrapper.SetObject(Obj);
  581. Result := Assigned(Wrapper.ObjectWrapped);
  582. if Result then
  583. Wrapper.NeedReInit := True;
  584. end
  585. else
  586. begin
  587. if Assigned(Obj) then
  588. try
  589. FreeAndNil(Obj);
  590. except
  591. end;
  592. end;
  593. finally
  594. csObjectMgr.Leave;
  595. end;
  596. end;
  597. function TCnCustomObjectPool.DoFreeOne(Wrapper: TCnObjectWrapper;
  598. var Obj: TObject): Boolean;
  599. begin
  600. csObjectMgr.Enter;
  601. try
  602. Result := True;
  603. if Assigned(OnFreeOne) then
  604. OnFreeOne(Self, Wrapper, Obj, Result);
  605. if Assigned(Obj) then
  606. try
  607. FreeAndNil(Obj);
  608. except
  609. end;
  610. finally
  611. csObjectMgr.Leave;
  612. end;
  613. end;
  614. function TCnCustomObjectPool.DoGetOne(Wrapper: TCnObjectWrapper;
  615. var Obj: TObject): Boolean;
  616. begin
  617. csObjectMgr.Enter;
  618. try
  619. Result := True;
  620. if Assigned(OnGetOne) then
  621. OnGetOne(Self, Wrapper, Obj, Result);
  622. finally
  623. csObjectMgr.Leave;
  624. end;
  625. end;
  626. function TCnCustomObjectPool.DoReInitOne(Wrapper: TCnObjectWrapper;
  627. var Obj: TObject): Boolean;
  628. begin
  629. csObjectMgr.Enter;
  630. try
  631. Result := True;
  632. if Assigned(OnReInitOne) then
  633. OnReInitOne(Self, Wrapper, Obj, Result);
  634. if Result then
  635. Wrapper.NeedReInit := False;
  636. finally
  637. csObjectMgr.Leave;
  638. end;
  639. end;
  640. function TCnCustomObjectPool.DoReleaseOne(Wrapper: TCnObjectWrapper;
  641. var Obj: TObject): Boolean;
  642. begin
  643. csObjectMgr.Enter;
  644. try
  645. Result := True;
  646. if Assigned(OnReleaseOne) then
  647. OnReleaseOne(Self, Wrapper, Obj, Result);
  648. finally
  649. csObjectMgr.Leave;
  650. end;
  651. end;
  652. function TCnCustomObjectPool.GetCount: Integer;
  653. begin
  654. csObjectMgr.Enter;
  655. try
  656. Result := FObjectList.Count;
  657. finally
  658. csObjectMgr.Leave;
  659. end;
  660. end;
  661. function TCnCustomObjectPool.GetInfo: string;
  662. var
  663. i, iCount: Integer;
  664. begin
  665. Result := 'Too busy to get info.';
  666. if csObjectMgr.TryEnter then
  667. try
  668. iCount := FObjectList.Count;
  669. Result := 'Object Count = ' + IntToStr(iCount);
  670. for i := 0 to iCount - 1 do
  671. Result := Result + #13#10 + TCnObjectWrapper(FObjectList.Items[i]).GetInfo;
  672. finally
  673. csObjectMgr.Leave;
  674. end;
  675. end;
  676. function TCnCustomObjectPool.GetOne(var Obj: TObject;
  677. const go: TCnObjectPoolGetOption): TCnObjectPoolGetResult;
  678. function TryGetOne: TCnObjectWrapper;
  679. var
  680. i, iFilter, iCount: Integer;
  681. objwrap: TCnObjectWrapper;
  682. dResult, dtemp: Double;
  683. cResult, ctemp: Cardinal;
  684. iResult, itmp, iMinRef, iValid: Integer;
  685. bHasRef, btemp: Boolean;
  686. begin
  687. Result := nil;
  688. iCount := FObjectList.Count;
  689. if iCount = 0 then
  690. Exit;
  691. iFilter := -1;
  692. iResult := -1;
  693. iMinRef := -1;
  694. iValid := -1;
  695. dResult := -1;
  696. cResult := 0;
  697. bHasRef := True; // 有引用的优先级小于无引用的
  698. if (go <> goNone) or (PolicyOnBusy <> bpReuse) then
  699. begin
  700. case PolicyOnGet of
  701. gpReuse:
  702. begin
  703. for i := 0 to iCount - 1 do
  704. begin
  705. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  706. if objwrap.RefCount > 0 then
  707. Continue;
  708. if objwrap.RefCount = 0 then
  709. begin
  710. iFilter := i;
  711. Break;
  712. end;
  713. end;
  714. end;
  715. gpReuseMaxWorkEff, gpMaxWorkEff:
  716. begin // 最大工作效率就是WorkEff最小
  717. for i := 0 to iCount - 1 do
  718. begin
  719. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  720. if objwrap.RefCount > 0 then
  721. Continue;
  722. dtemp := objwrap.WorkEff;
  723. if dtemp = 0 then
  724. begin
  725. iFilter := i;
  726. Break;
  727. end
  728. else
  729. begin
  730. if (dResult < 0) or (dtemp < dResult) then
  731. begin
  732. dResult := dtemp;
  733. iFilter := i;
  734. end;
  735. end;
  736. end;
  737. end;
  738. gpReuseMinWorkCount, gpMinWorkCount:
  739. begin
  740. for i := 0 to iCount - 1 do
  741. begin
  742. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  743. if objwrap.RefCount > 0 then
  744. Continue;
  745. if objwrap.WorkCount = 0 then
  746. begin
  747. iFilter := i;
  748. Break;
  749. end
  750. else
  751. begin
  752. ctemp := objwrap.WorkCount;
  753. if (cResult = 0) or (ctemp < cResult) then
  754. begin
  755. cResult := ctemp;
  756. iFilter := i;
  757. end;
  758. end;
  759. end;
  760. end;
  761. gpReuseMaxWorkCount, gpMaxWorkCount:
  762. begin
  763. for i := 0 to iCount - 1 do
  764. begin
  765. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  766. if objwrap.RefCount > 0 then
  767. Continue;
  768. if iValid < 0 then
  769. iValid := i;
  770. ctemp := objwrap.WorkCount;
  771. if ctemp > cResult then
  772. begin
  773. cResult := ctemp;
  774. iFilter := i;
  775. end;
  776. end;
  777. if iFilter < 0 then
  778. iFilter := iValid;
  779. end;
  780. gpReuseMinWorkTime, gpMinWorkTime:
  781. begin
  782. for i := 0 to iCount - 1 do
  783. begin
  784. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  785. if objwrap.RefCount > 0 then
  786. Continue;
  787. if objwrap.WorkTime = 0 then
  788. begin
  789. iFilter := i;
  790. Break;
  791. end
  792. else
  793. begin
  794. ctemp := objwrap.WorkTime;
  795. if (cResult = 0) or (ctemp < cResult) then
  796. begin
  797. cResult := ctemp;
  798. iFilter := i;
  799. end;
  800. end;
  801. end;
  802. end;
  803. gpReuseMaxWorkTime, gpMaxWorkTime:
  804. begin
  805. for i := 0 to iCount - 1 do
  806. begin
  807. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  808. if objwrap.RefCount > 0 then
  809. Continue;
  810. if iValid < 0 then
  811. iValid := i;
  812. ctemp := objwrap.WorkTime;
  813. if ctemp > cResult then
  814. begin
  815. cResult := ctemp;
  816. iFilter := i;
  817. end;
  818. end;
  819. if iFilter < 0 then
  820. iFilter := iValid;
  821. end;
  822. end;
  823. end
  824. else
  825. begin
  826. case PolicyOnGet of
  827. gpReuse:
  828. begin
  829. for i := 0 to iCount - 1 do
  830. begin
  831. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  832. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  833. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  834. Continue;
  835. if objwrap.RefCount = 0 then
  836. begin
  837. iFilter := i;
  838. Break;
  839. end
  840. else
  841. begin
  842. itmp := objwrap.RefCount;
  843. if (iResult < 0) or (itmp < iResult) then
  844. begin
  845. iResult := itmp;
  846. iFilter := i;
  847. end;
  848. end;
  849. end;
  850. end;
  851. gpReuseMaxWorkEff:
  852. begin
  853. for i := 0 to iCount - 1 do
  854. begin
  855. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  856. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  857. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  858. Continue;
  859. itmp := objwrap.RefCount;
  860. if (iMinRef < 0) or (itmp <= iMinRef) then
  861. begin
  862. btemp := itmp < iMinRef;
  863. iMinRef := itmp;
  864. dtemp := objwrap.WorkEff;
  865. if btemp or (dResult < 0) or (dtemp < dResult) then
  866. begin
  867. dResult := dtemp;
  868. iFilter := i;
  869. end;
  870. end;
  871. end;
  872. end;
  873. gpReuseMinWorkCount:
  874. begin
  875. for i := 0 to iCount - 1 do
  876. begin
  877. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  878. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  879. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  880. Continue;
  881. itmp := objwrap.RefCount;
  882. if (iMinRef < 0) or (itmp <= iMinRef) then
  883. begin
  884. btemp := itmp < iMinRef;
  885. iMinRef := itmp;
  886. ctemp := objwrap.WorkCount;
  887. if btemp or (cResult = 0) or (ctemp < cResult) then
  888. begin
  889. cResult := ctemp;
  890. iFilter := i;
  891. end;
  892. end;
  893. end;
  894. end;
  895. gpReuseMaxWorkCount:
  896. begin
  897. for i := 0 to iCount - 1 do
  898. begin
  899. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  900. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  901. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  902. Continue;
  903. itmp := objwrap.RefCount;
  904. if (iMinRef < 0) or (itmp <= iMinRef) then
  905. begin
  906. btemp := itmp < iMinRef;
  907. if (iValid < 0) or btemp then
  908. iValid := i;
  909. iMinRef := itmp;
  910. ctemp := objwrap.WorkCount;
  911. if btemp or (ctemp > cResult) then
  912. begin
  913. cResult := ctemp;
  914. iFilter := i;
  915. end;
  916. end;
  917. end;
  918. if iFilter < 0 then
  919. iFilter := iValid;
  920. end;
  921. gpReuseMinWorkTime:
  922. begin
  923. for i := 0 to iCount - 1 do
  924. begin
  925. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  926. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  927. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  928. Continue;
  929. itmp := objwrap.RefCount;
  930. if (iMinRef < 0) or (itmp <= iMinRef) then
  931. begin
  932. btemp := itmp < iMinRef;
  933. iMinRef := itmp;
  934. ctemp := objwrap.WorkTime;
  935. if btemp or (cResult = 0) or (ctemp < cResult) then
  936. begin
  937. cResult := ctemp;
  938. iFilter := i;
  939. end;
  940. end;
  941. end;
  942. end;
  943. gpReuseMaxWorkTime:
  944. begin
  945. for i := 0 to iCount - 1 do
  946. begin
  947. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  948. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  949. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  950. Continue;
  951. itmp := objwrap.RefCount;
  952. if (iMinRef < 0) or (itmp <= iMinRef) then
  953. begin
  954. btemp := itmp < iMinRef;
  955. if (iValid < 0) or btemp then
  956. iValid := i;
  957. iMinRef := itmp;
  958. ctemp := objwrap.WorkTime;
  959. if btemp or (ctemp > cResult) then
  960. begin
  961. cResult := ctemp;
  962. iFilter := i;
  963. end;
  964. end;
  965. end;
  966. if iFilter < 0 then
  967. iFilter := iValid;
  968. end;
  969. gpMaxWorkEff:
  970. begin
  971. for i := 0 to iCount - 1 do
  972. begin
  973. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  974. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  975. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  976. Continue;
  977. btemp := objwrap.RefCount > 0;
  978. if bHasRef or (not btemp) then
  979. begin
  980. bHasRef := btemp;
  981. dtemp := objwrap.WorkEff;
  982. if (dResult < 0) or (dtemp < dResult) then
  983. begin
  984. dResult := dtemp;
  985. iFilter := i;
  986. end;
  987. end;
  988. end;
  989. end;
  990. gpMinWorkCount:
  991. begin
  992. for i := 0 to iCount - 1 do
  993. begin
  994. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  995. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  996. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  997. Continue;
  998. btemp := objwrap.RefCount > 0;
  999. if bHasRef or (not btemp) then
  1000. begin
  1001. bHasRef := btemp;
  1002. ctemp := objwrap.WorkCount;
  1003. if (cResult = 0) or (ctemp < cResult) then
  1004. begin
  1005. cResult := ctemp;
  1006. iFilter := i;
  1007. end;
  1008. end;
  1009. end;
  1010. end;
  1011. gpMaxWorkCount:
  1012. begin
  1013. for i := 0 to iCount - 1 do
  1014. begin
  1015. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  1016. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  1017. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  1018. Continue;
  1019. btemp := objwrap.RefCount > 0;
  1020. if bHasRef or (not btemp) then
  1021. begin
  1022. if (iValid < 0) or (not btemp) then
  1023. iValid := i;
  1024. bHasRef := btemp;
  1025. ctemp := objwrap.WorkCount;
  1026. if ctemp > cResult then
  1027. begin
  1028. cResult := ctemp;
  1029. iFilter := i;
  1030. end;
  1031. end;
  1032. end;
  1033. if iFilter < 0 then
  1034. iFilter := iValid;
  1035. end;
  1036. gpMinWorkTime:
  1037. begin
  1038. for i := 0 to iCount - 1 do
  1039. begin
  1040. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  1041. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  1042. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  1043. Continue;
  1044. btemp := objwrap.RefCount > 0;
  1045. if bHasRef or (not btemp) then
  1046. begin
  1047. bHasRef := btemp;
  1048. ctemp := objwrap.WorkTime;
  1049. if (cResult = 0) or (ctemp < cResult) then
  1050. begin
  1051. cResult := ctemp;
  1052. iFilter := i;
  1053. end;
  1054. end;
  1055. end;
  1056. end;
  1057. gpMaxWorkTime:
  1058. begin
  1059. for i := 0 to iCount - 1 do
  1060. begin
  1061. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  1062. if ((not objwrap.CanReuse) and (objwrap.RefCount > 0)) or
  1063. ((FPeakCount > 0) and (objwrap.RefCount >= FPeakCount)) then
  1064. Continue;
  1065. btemp := objwrap.RefCount > 0;
  1066. if bHasRef or (not btemp) then
  1067. begin
  1068. if (iValid < 0) or (not btemp) then
  1069. iValid := i;
  1070. bHasRef := btemp;
  1071. ctemp := objwrap.WorkTime;
  1072. if ctemp > cResult then
  1073. begin
  1074. cResult := ctemp;
  1075. iFilter := i;
  1076. end;
  1077. end;
  1078. end;
  1079. if iFilter < 0 then
  1080. iFilter := iValid;
  1081. end;
  1082. end;
  1083. end;
  1084. if iFilter >= 0 then
  1085. begin
  1086. Result := TCnObjectWrapper(FObjectList.Items[iFilter]);
  1087. if (go = goNone) and (PolicyOnBusy = bpReuse) and
  1088. (FLowLoadCount > 0) and (Result.RefCount >= FLowLoadCount) then
  1089. begin
  1090. if CanIncObject then
  1091. Result := IncObject(False);
  1092. end;
  1093. end;
  1094. end;
  1095. type
  1096. THandleID = (hidRelease, hidTerminate, hidWaitTimeOut);
  1097. var
  1098. Handles: array[THandleID] of THandle;
  1099. hWaitTimeOut, hTimer: THandle;
  1100. objwrap: TCnObjectWrapper;
  1101. begin
  1102. hTimer := 0;
  1103. hWaitTimeOut := CreateEvent(nil, True, False, nil);
  1104. Handles[hidWaitTimeOut] := hWaitTimeOut;
  1105. //if hWaitTimeOut = nil then wait timeout cannot work
  1106. try
  1107. Result := grGetFail;
  1108. while True do
  1109. begin
  1110. if bTerminated then
  1111. begin
  1112. Obj := nil;
  1113. Result := grGetFail;
  1114. Break;
  1115. end;
  1116. csObjectMgr.Enter;
  1117. try
  1118. objwrap := nil;
  1119. while True do
  1120. begin
  1121. if bTerminated then
  1122. begin
  1123. Obj := nil;
  1124. Result := grGetFail;
  1125. Break;
  1126. end;
  1127. objwrap := TryGetOne;
  1128. if objwrap = nil then
  1129. begin
  1130. if CanIncObject then
  1131. begin
  1132. IncObject(True); //注意:如果总是创建失败可能会陷入死循环
  1133. end
  1134. else
  1135. begin
  1136. Break;
  1137. end;
  1138. end
  1139. else
  1140. begin
  1141. Break;
  1142. end;
  1143. end;
  1144. if objwrap <> nil then
  1145. begin
  1146. Obj := objwrap.ObjectWrapped;
  1147. if not DoGetOne(objwrap, Obj) then
  1148. begin
  1149. Obj := nil;
  1150. Result := grGetFail;
  1151. Break;
  1152. end;
  1153. if objwrap.RefCount > 0 then
  1154. begin
  1155. Result := grReuse;
  1156. end
  1157. else
  1158. begin
  1159. if (objwrap.FNeedReInit) or (goReInit = go) then
  1160. begin
  1161. try
  1162. if DoReInitOne(objwrap, Obj) then
  1163. Result := grSuccess
  1164. else
  1165. Result := grReinitFail;
  1166. except
  1167. Result := grReinitFail;
  1168. end;
  1169. end
  1170. else
  1171. begin
  1172. Result := grSuccess;
  1173. end;
  1174. end;
  1175. if Assigned(FObjectClass) and (not (Obj is FObjectClass)) then
  1176. begin
  1177. Obj := nil;
  1178. Result := grGetError;
  1179. Break;
  1180. end;
  1181. objwrap.CanReuse := go = goNone; //goMutex,goReinit的对象都不能被重用
  1182. objwrap.IncRef;
  1183. Break;
  1184. end
  1185. else
  1186. begin
  1187. case PolicyOnBusy of
  1188. bpReuse:
  1189. begin
  1190. case PolicyOnPeak of
  1191. bpGetFail:
  1192. begin
  1193. Obj := nil;
  1194. Result := grGetFail;
  1195. Break;
  1196. end;
  1197. bpWait:
  1198. begin
  1199. if (hTimer = 0) and (WaitTimeOut > 0) then
  1200. begin //需要考量该函数的开销,而且是否需要调用timebeginperiod等函数?
  1201. hTimer := timeSetEvent(WaitTimeOut, 100, TFNTimeCallBack(hWaitTimeOut), 0, TIME_ONESHOT or TIME_CALLBACK_EVENT_SET);
  1202. end;
  1203. end;
  1204. end;
  1205. end;
  1206. bpGetFail:
  1207. begin
  1208. Obj := nil;
  1209. Result := grGetFail;
  1210. Break;
  1211. end;
  1212. bpWait:
  1213. begin
  1214. if (hTimer = 0) and (WaitTimeOut > 0) then
  1215. begin
  1216. hTimer := timeSetEvent(WaitTimeOut, 100, TFNTimeCallBack(hWaitTimeOut), 0, TIME_ONESHOT or TIME_CALLBACK_EVENT_SET);
  1217. end;
  1218. end;
  1219. end;
  1220. end;
  1221. finally
  1222. csObjectMgr.Leave;
  1223. end;
  1224. if bTerminated then
  1225. begin
  1226. Obj := nil;
  1227. Result := grGetFail;
  1228. Break;
  1229. end;
  1230. try
  1231. case WaitForMultipleObjects(Length(Handles), @Handles, False, INFINITE) of
  1232. WAIT_OBJECT_0 + Ord(hidRelease):
  1233. begin
  1234. ResetEvent(hRelease);
  1235. end;
  1236. WAIT_OBJECT_0 + Ord(hidTerminate):
  1237. begin
  1238. Obj := nil;
  1239. Result := grGetFail;
  1240. Break;
  1241. end;
  1242. WAIT_OBJECT_0 + Ord(hidWaitTimeOut):
  1243. begin
  1244. timeKillEvent(hTimer);
  1245. hTimer := 0;
  1246. Obj := nil;
  1247. Result := grWaitFail;
  1248. Break;
  1249. end;
  1250. else
  1251. end;
  1252. finally
  1253. end;
  1254. end; // end while True
  1255. finally
  1256. if hTimer <> 0 then
  1257. timeKillEvent(hTimer);
  1258. CloseHandle(hWaitTimeOut);
  1259. end;
  1260. end;
  1261. function TCnCustomObjectPool.CanIncObject: Boolean;
  1262. begin
  1263. Result := (FMaxSize <= 0) or (FMaxSize > FObjectList.Count);
  1264. end;
  1265. function TCnCustomObjectPool.IncObject(const bSetEvent: Boolean): TCnObjectWrapper;
  1266. var
  1267. obj: TObject;
  1268. objwrap: TCnObjectWrapper;
  1269. begin
  1270. Result := nil;
  1271. csObjectMgr.Enter;
  1272. try
  1273. if (FMaxSize > 0) and (FMaxSize <= FObjectList.Count) then
  1274. Exit;
  1275. objwrap := FObjectWrapperClass.Create(nil);
  1276. try
  1277. obj := nil;
  1278. if not DoCreateOne(objwrap, obj) then
  1279. begin
  1280. if Assigned(obj) then
  1281. if not DoFreeOne(objwrap, obj) then
  1282. begin
  1283. if Assigned(obj) then
  1284. try
  1285. obj.Free;
  1286. except
  1287. end;
  1288. end;
  1289. objwrap.Free;
  1290. end
  1291. else
  1292. begin
  1293. if AddObjWrapper(objwrap) then
  1294. begin
  1295. objwrap.SetOwner(Self);
  1296. if bSetEvent then
  1297. begin
  1298. SetEvent(hRelease);
  1299. end;
  1300. Result := objwrap;
  1301. end
  1302. else
  1303. begin
  1304. if Assigned(objwrap) then
  1305. try
  1306. objwrap.Free;
  1307. except
  1308. end;
  1309. if Assigned(obj) then
  1310. try
  1311. obj.Free;
  1312. except
  1313. end;
  1314. end;
  1315. end;
  1316. except
  1317. objwrap.Free;
  1318. raise ;
  1319. end;
  1320. finally
  1321. csObjectMgr.Leave;
  1322. end;
  1323. end;
  1324. procedure TCnCustomObjectPool.ReInitAll;
  1325. var
  1326. i, iCount: Integer;
  1327. begin
  1328. csObjectMgr.Enter;
  1329. try
  1330. iCount := FObjectList.Count;
  1331. for i := 0 to iCount - 1 do
  1332. TCnObjectWrapper(FObjectList.Items[i]).NeedReInit := True;
  1333. finally
  1334. csObjectMgr.Leave;
  1335. end;
  1336. end;
  1337. procedure TCnCustomObjectPool.ReleaseOne(var Obj;
  1338. const ro: TCnObjectPoolReleaseOption);
  1339. var
  1340. i, iCount: Integer;
  1341. objwrap: TCnObjectWrapper;
  1342. begin
  1343. csObjectMgr.Enter;
  1344. try
  1345. iCount := FObjectList.Count;
  1346. for i := 0 to iCount - 1 do
  1347. begin
  1348. objwrap := TCnObjectWrapper(FObjectList.Items[i]);
  1349. if Assigned(objwrap) then
  1350. begin
  1351. if objwrap.FObject = TObject(Obj) then
  1352. begin
  1353. try
  1354. DoReleaseOne(objwrap, TObject(Obj));
  1355. except
  1356. end;
  1357. TObject(Obj) := nil; //该指针已经没有用途了
  1358. objwrap.CanReuse := True; //如果是可重用的对象该值已经是真,如果是不可重用的释放之后就可重用了
  1359. case ro of
  1360. roNone:
  1361. begin
  1362. objwrap.DecRef;
  1363. SetEvent(hRelease);
  1364. end;
  1365. roReInit:
  1366. begin
  1367. objwrap.DecRef;
  1368. objwrap.NeedReInit := True;
  1369. SetEvent(hRelease);
  1370. end;
  1371. roDelete:
  1372. begin
  1373. try
  1374. objwrap.Free;
  1375. except
  1376. end;
  1377. end;
  1378. roFree:
  1379. begin
  1380. DecObject(objwrap);
  1381. end;
  1382. end;
  1383. CreateBaseCountObjects(True);
  1384. Break;
  1385. end;
  1386. end;
  1387. end;
  1388. finally
  1389. csObjectMgr.Leave;
  1390. end;
  1391. end;
  1392. function TCnCustomObjectPool.RemoveObjWrapper(
  1393. ObjWrapper: TCnObjectWrapper): Boolean;
  1394. var
  1395. i: Integer;
  1396. begin
  1397. csObjectMgr.Enter;
  1398. try
  1399. i := FObjectList.IndexOf(ObjWrapper);
  1400. Result := i >= 0;
  1401. if Result then
  1402. FObjectList.Delete(i);
  1403. finally
  1404. csObjectMgr.Leave;
  1405. end;
  1406. end;
  1407. procedure TCnCustomObjectPool.SetLowLoadCount(const Value: Integer);
  1408. begin
  1409. csObjectMgr.Enter;
  1410. try
  1411. FLowLoadCount := Value;
  1412. finally
  1413. csObjectMgr.Leave;
  1414. end;
  1415. end;
  1416. procedure TCnCustomObjectPool.SetMinSize(const Value: Integer);
  1417. begin
  1418. csObjectMgr.Enter;
  1419. try
  1420. FMinSize := Value;
  1421. CreateBaseCountObjects(False);
  1422. finally
  1423. csObjectMgr.Leave;
  1424. end;
  1425. end;
  1426. procedure TCnCustomObjectPool.SetObjectClass(const Value: TClass);
  1427. begin
  1428. csObjectMgr.Enter;
  1429. try
  1430. if Assigned(FOnCreateOne) then
  1431. raise Exception.Create('Cannot set ObjectClass while OnCreateOne not null.');
  1432. if (FObjectList.Count = 0) or
  1433. ((FObjectClass = nil) and Assigned(Value)) then
  1434. begin
  1435. FObjectClass := Value;
  1436. CreateBaseCountObjects(False);
  1437. end
  1438. else
  1439. begin
  1440. raise Exception.Create('Cannot change ObjectClass while ObjectList not null and assigned ObjectClass.');
  1441. end;
  1442. finally
  1443. csObjectMgr.Leave;
  1444. end;
  1445. end;
  1446. procedure TCnCustomObjectPool.SetPeakCount(const Value: Integer);
  1447. begin
  1448. csObjectMgr.Enter;
  1449. try
  1450. if (FPeakCount <> Value) and (Value >= 0) then
  1451. FPeakCount := Value;
  1452. finally
  1453. csObjectMgr.Leave;
  1454. end;
  1455. end;
  1456. procedure TCnCustomObjectPool.SetOnCreateOne(const Value: TOPEvent);
  1457. begin
  1458. //为防止ObjectClass与OnCreateOne冲突,所以设定了OnCreateOne则清空ObjectClass
  1459. if Assigned(Value) then
  1460. FObjectClass := nil;
  1461. FOnCreateOne := Value;
  1462. end;
  1463. procedure TCnCustomObjectPool.GetComponentInfo(var AName, Author, Email,
  1464. Comment: string);
  1465. begin
  1466. end;
  1467. { TCnObjectPool }
  1468. constructor TCnObjectPool.CreateSpecial(AOwner: TComponent;
  1469. AObjectWrapperClass: TCnObjectWrapperClass);
  1470. begin
  1471. inherited;
  1472. end;
  1473. procedure TCnObjectPool.GetComponentInfo(var AName, Author, Email,
  1474. Comment: string);
  1475. begin
  1476. AName := SCnObjectPoolName;
  1477. Author := SCnPack_Shenloqi;
  1478. Email := SCnPack_ShenloqiEmail;
  1479. Comment := SCnObjectPoolComment;
  1480. end;
  1481. function TCnObjectPool.GetObject(var Obj: TObject;
  1482. const go: TCnObjectPoolGetOption): TCnObjectPoolGetResult;
  1483. begin
  1484. Result := GetOne(Obj, go);
  1485. end;
  1486. procedure TCnObjectPool.ReleaseObject(var Obj;
  1487. const ro: TCnObjectPoolReleaseOption);
  1488. begin
  1489. ReleaseOne(Obj, ro);
  1490. end;
  1491. end.