From cfeb3da3f48004ae042b6a226ea6bbae9b4ccddc Mon Sep 17 00:00:00 2001 From: bergmann Date: Sat, 7 Jan 2017 13:03:06 +0100 Subject: [PATCH] * enumerator will track changes on enumerated list * some small fixes --- tests/tests.lpi | 4 - tests/tests.lps | 297 ++++++++++++++------------- tests/uutlListTest.pas | 263 ++++++++++++++++++++++++ tests/uutlObservableHashSetTests.pas | 5 +- tests/uutlObservableListTests.pas | 5 +- tests/uutlObservableMapTests.pas | 5 +- uutlCommon.pas | 35 +++- uutlComparer.pas | 12 +- uutlEnumerator.pas | 1 + uutlEvent.pas | 64 ++++-- uutlListBase.pas | 109 +++++++++- uutlLogger.pas | 14 +- uutlObservable.pas | 191 ++++++----------- uutlSyncObjs.pas | 9 +- 14 files changed, 684 insertions(+), 330 deletions(-) diff --git a/tests/tests.lpi b/tests/tests.lpi index 5222c17..476bbe3 100644 --- a/tests/tests.lpi +++ b/tests/tests.lpi @@ -9,10 +9,6 @@ <ResourceType Value="res"/> <UseXPManifest Value="True"/> - <XPManifest> - <TextName Value="CompanyName.ProductName.AppName"/> - <TextDesc Value="Your application description."/> - </XPManifest> <Icon Value="0"/> </General> <BuildModes Count="1"> diff --git a/tests/tests.lps b/tests/tests.lps index 6a5cd17..50f01de 100644 --- a/tests/tests.lps +++ b/tests/tests.lps @@ -4,20 +4,21 @@ <PathDelim Value="\"/> <Version Value="10"/> <BuildModes Active="Default"/> - <Units Count="66"> + <Units Count="68"> <Unit0> <Filename Value="tests.lpr"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="54" Y="12"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit0> <Unit1> <Filename Value="..\uutlGenerics.pas"/> <IsPartOfProject Value="True"/> - <TopLine Value="173"/> - <CursorPos X="30" Y="188"/> - <UsageCount Value="79"/> + <EditorIndex Value="7"/> + <TopLine Value="1003"/> + <CursorPos Y="1021"/> + <UsageCount Value="81"/> <Loaded Value="True"/> </Unit1> <Unit2> @@ -25,7 +26,7 @@ <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="11" Y="13"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit2> <Unit3> <Filename Value="..\uutlCommon.pas"/> @@ -33,25 +34,24 @@ <EditorIndex Value="-1"/> <TopLine Value="206"/> <CursorPos X="10" Y="225"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit3> <Unit4> <Filename Value="..\uutlListBase.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="1"/> - <TopLine Value="79"/> - <CursorPos X="8" Y="100"/> - <UsageCount Value="79"/> + <TopLine Value="100"/> + <CursorPos X="72" Y="113"/> + <UsageCount Value="81"/> <Loaded Value="True"/> </Unit4> <Unit5> <Filename Value="uutlListTest.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="-1"/> - <WindowIndex Value="1"/> - <TopLine Value="357"/> - <CursorPos X="7" Y="376"/> - <UsageCount Value="79"/> + <EditorIndex Value="3"/> + <TopLine Value="573"/> + <CursorPos Y="588"/> + <UsageCount Value="81"/> + <Loaded Value="True"/> </Unit5> <Unit6> <Filename Value="uutlQueueTests.pas"/> @@ -59,7 +59,7 @@ <EditorIndex Value="-1"/> <TopLine Value="250"/> <CursorPos X="49" Y="260"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit6> <Unit7> <Filename Value="uutlStackTests.pas"/> @@ -67,21 +67,22 @@ <EditorIndex Value="-1"/> <TopLine Value="246"/> <CursorPos X="24" Y="263"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit7> <Unit8> <Filename Value="uTestHelper.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="-1"/> + <EditorIndex Value="4"/> <CursorPos X="3" Y="12"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> + <Loaded Value="True"/> </Unit8> <Unit9> <Filename Value="..\uutlComparer.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="90" Y="6"/> - <UsageCount Value="69"/> + <UsageCount Value="71"/> </Unit9> <Unit10> <Filename Value="..\uutlAlgorithm.pas"/> @@ -89,23 +90,22 @@ <EditorIndex Value="-1"/> <TopLine Value="138"/> <CursorPos Y="153"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit10> <Unit11> <Filename Value="uutlHashSetTests.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="32" Y="13"/> - <UsageCount Value="79"/> + <UsageCount Value="81"/> </Unit11> <Unit12> <Filename Value="uutlAlgorithmTests.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="8"/> + <EditorIndex Value="-1"/> <TopLine Value="72"/> <CursorPos X="43" Y="87"/> - <UsageCount Value="78"/> - <Loaded Value="True"/> + <UsageCount Value="80"/> </Unit12> <Unit13> <Filename Value="uutlMapTests.pas"/> @@ -113,26 +113,24 @@ <EditorIndex Value="-1"/> <TopLine Value="206"/> <CursorPos X="66" Y="221"/> - <UsageCount Value="77"/> + <UsageCount Value="79"/> </Unit13> <Unit14> <Filename Value="..\uutlEnumerator.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="6"/> - <TopLine Value="324"/> - <CursorPos X="42" Y="340"/> - <UsageCount Value="76"/> + <EditorIndex Value="1"/> + <TopLine Value="90"/> + <CursorPos X="5" Y="105"/> + <UsageCount Value="78"/> <Loaded Value="True"/> </Unit14> <Unit15> <Filename Value="uutlEnumeratorTests.pas"/> <IsPartOfProject Value="True"/> - <IsVisibleTab Value="True"/> - <EditorIndex Value="7"/> - <TopLine Value="617"/> - <CursorPos X="74" Y="634"/> - <UsageCount Value="76"/> - <Loaded Value="True"/> + <EditorIndex Value="-1"/> + <TopLine Value="615"/> + <CursorPos X="34" Y="631"/> + <UsageCount Value="78"/> </Unit15> <Unit16> <Filename Value="..\uutlFilter.pas"/> @@ -140,40 +138,38 @@ <EditorIndex Value="-1"/> <TopLine Value="17"/> <CursorPos X="13" Y="159"/> - <UsageCount Value="72"/> + <UsageCount Value="74"/> </Unit16> <Unit17> <Filename Value="..\uutlInterfaces.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="5"/> - <TopLine Value="31"/> - <CursorPos X="70" Y="47"/> - <UsageCount Value="72"/> + <EditorIndex Value="2"/> + <TopLine Value="34"/> + <CursorPos X="5" Y="40"/> + <UsageCount Value="74"/> <Loaded Value="True"/> </Unit17> <Unit18> <Filename Value="..\uutlLinq.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="3"/> + <EditorIndex Value="-1"/> <TopLine Value="391"/> <CursorPos X="31" Y="417"/> - <UsageCount Value="63"/> - <Loaded Value="True"/> + <UsageCount Value="65"/> </Unit18> <Unit19> <Filename Value="uutlLinqTests.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="4"/> + <EditorIndex Value="-1"/> <TopLine Value="622"/> <CursorPos X="23" Y="650"/> - <UsageCount Value="63"/> - <Loaded Value="True"/> + <UsageCount Value="65"/> </Unit19> <Unit20> <Filename Value="..\uutlTypes.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> - <UsageCount Value="63"/> + <UsageCount Value="65"/> </Unit20> <Unit21> <Filename Value="..\uutlSyncObjs.pas"/> @@ -181,7 +177,7 @@ <EditorIndex Value="-1"/> <TopLine Value="241"/> <CursorPos X="20" Y="263"/> - <UsageCount Value="57"/> + <UsageCount Value="59"/> </Unit21> <Unit22> <Filename Value="..\uutlLogger.pas"/> @@ -189,7 +185,7 @@ <EditorIndex Value="-1"/> <TopLine Value="419"/> <CursorPos X="55" Y="434"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit22> <Unit23> <Filename Value="..\uutlXmlHelper.pas"/> @@ -197,7 +193,7 @@ <EditorIndex Value="-1"/> <TopLine Value="188"/> <CursorPos X="26" Y="203"/> - <UsageCount Value="56"/> + <UsageCount Value="58"/> </Unit23> <Unit24> <Filename Value="..\uutlStreamHelper.pas"/> @@ -205,7 +201,7 @@ <EditorIndex Value="-1"/> <TopLine Value="216"/> <CursorPos X="10" Y="241"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit24> <Unit25> <Filename Value="..\uutlCompression.pas"/> @@ -214,7 +210,7 @@ <WindowIndex Value="-1"/> <TopLine Value="-1"/> <CursorPos X="-1" Y="-1"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit25> <Unit26> <Filename Value="..\uutlEmbeddedProfiler.pas"/> @@ -223,7 +219,7 @@ <WindowIndex Value="-1"/> <TopLine Value="-1"/> <CursorPos X="-1" Y="-1"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit26> <Unit27> <Filename Value="..\uutlKeyCodes.pas"/> @@ -232,7 +228,7 @@ <WindowIndex Value="-1"/> <TopLine Value="-1"/> <CursorPos X="-1" Y="-1"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit27> <Unit28> <Filename Value="..\uutlMCF.pas"/> @@ -241,7 +237,7 @@ <WindowIndex Value="-1"/> <TopLine Value="-1"/> <CursorPos X="-1" Y="-1"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit28> <Unit29> <Filename Value="..\uutlSScanf.pas"/> @@ -250,7 +246,7 @@ <WindowIndex Value="-1"/> <TopLine Value="-1"/> <CursorPos X="-1" Y="-1"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit29> <Unit30> <Filename Value="..\uutlThreads.pas"/> @@ -259,14 +255,14 @@ <WindowIndex Value="-1"/> <TopLine Value="-1"/> <CursorPos X="-1" Y="-1"/> - <UsageCount Value="55"/> + <UsageCount Value="57"/> </Unit30> <Unit31> <Filename Value="..\uutlEvent.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="11" Y="35"/> - <UsageCount Value="54"/> + <UsageCount Value="56"/> </Unit31> <Unit32> <Filename Value="..\uutlEventManager.pas"/> @@ -274,7 +270,7 @@ <EditorIndex Value="-1"/> <TopLine Value="246"/> <CursorPos X="39" Y="264"/> - <UsageCount Value="54"/> + <UsageCount Value="56"/> </Unit32> <Unit33> <Filename Value="..\uutlObservable.pas"/> @@ -282,41 +278,39 @@ <EditorIndex Value="-1"/> <TopLine Value="556"/> <CursorPos X="45" Y="572"/> - <UsageCount Value="54"/> + <UsageCount Value="56"/> </Unit33> <Unit34> <Filename Value="uutlObservableListTests.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> - <WindowIndex Value="1"/> - <TopLine Value="49"/> - <CursorPos Y="65"/> - <UsageCount Value="46"/> + <TopLine Value="36"/> + <CursorPos X="53" Y="52"/> + <UsageCount Value="48"/> </Unit34> <Unit35> <Filename Value="uutlObservableHashSetTests.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> - <WindowIndex Value="-1"/> - <TopLine Value="129"/> - <CursorPos Y="146"/> - <UsageCount Value="26"/> + <TopLine Value="46"/> + <CursorPos X="25" Y="62"/> + <UsageCount Value="28"/> </Unit35> <Unit36> <Filename Value="uutlObservableMapTests.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> - <CursorPos X="3" Y="13"/> - <UsageCount Value="25"/> + <TopLine Value="46"/> + <CursorPos X="22" Y="51"/> + <UsageCount Value="27"/> </Unit36> <Unit37> <Filename Value="uutlSetHelperTests.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="2"/> + <EditorIndex Value="-1"/> <TopLine Value="44"/> <CursorPos X="64" Y="54"/> - <UsageCount Value="22"/> - <Loaded Value="True"/> + <UsageCount Value="24"/> </Unit37> <Unit38> <Filename Value="..\uutlExceptions.pas"/> @@ -512,11 +506,29 @@ </Unit64> <Unit65> <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\FPCUnitCompatibleInterface.inc"/> - <EditorIndex Value="-1"/> - <TopLine Value="53"/> - <CursorPos X="104" Y="75"/> - <UsageCount Value="10"/> + <EditorIndex Value="5"/> + <TopLine Value="158"/> + <CursorPos Y="185"/> + <UsageCount Value="11"/> + <Loaded Value="True"/> </Unit65> + <Unit66> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <IsVisibleTab Value="True"/> + <EditorIndex Value="8"/> + <TopLine Value="3311"/> + <CursorPos X="30" Y="3325"/> + <UsageCount Value="11"/> + <Loaded Value="True"/> + </Unit66> + <Unit67> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFrameworkIfaces.pas"/> + <EditorIndex Value="6"/> + <TopLine Value="35"/> + <CursorPos X="3" Y="51"/> + <UsageCount Value="10"/> + <Loaded Value="True"/> + </Unit67> </Units> <OtherDefines Count="3"> <Define0 Value="UTL_ADVANCED_ENUMERATORS"/> @@ -525,124 +537,124 @@ </OtherDefines> <JumpHistory Count="30" HistoryIndex="29"> <Position1> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="561" Column="7" TopLine="554"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="139" TopLine="119"/> </Position1> <Position2> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="545" Column="16" TopLine="531"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="143" TopLine="119"/> </Position2> <Position3> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="540" Column="13" TopLine="524"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="135" Column="35" TopLine="119"/> </Position3> <Position4> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="31" Column="17" TopLine="15"/> + <Filename Value="uutlListTest.pas"/> + <Caret Line="612" Column="42" TopLine="594"/> </Position4> <Position5> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="109" Column="5" TopLine="90"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="105" TopLine="89"/> </Position5> <Position6> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="748" Column="16" TopLine="745"/> + <Filename Value="uutlListTest.pas"/> + <Caret Line="625" TopLine="610"/> </Position6> <Position7> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="105" Column="17" TopLine="89"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\FPCUnitCompatibleInterface.inc"/> + <Caret Line="184" TopLine="158"/> </Position7> <Position8> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="55" Column="65" TopLine="35"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <Caret Line="3327" TopLine="3306"/> </Position8> <Position9> - <Filename Value="..\uutlListBase.pas"/> - <Caret Line="34" Column="14" TopLine="10"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <Caret Line="3329" TopLine="3306"/> </Position9> <Position10> - <Filename Value="..\uutlListBase.pas"/> - <Caret Line="97" Column="54" TopLine="86"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <Caret Line="3332" TopLine="3306"/> </Position10> <Position11> - <Filename Value="..\uutlListBase.pas"/> - <Caret Line="182" Column="40" TopLine="164"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <Caret Line="3333" TopLine="3307"/> </Position11> <Position12> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="109" Column="49" TopLine="95"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <Caret Line="3335" TopLine="3309"/> </Position12> <Position13> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="22" Column="36" TopLine="14"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\TestFramework.pas"/> + <Caret Line="3337" TopLine="3311"/> </Position13> <Position14> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="60" Column="41" TopLine="37"/> + <Filename Value="C:\Zusatzprogramme\Lazarus\components_extra\fptest\src\FPCUnitCompatibleInterface.inc"/> + <Caret Line="185" TopLine="158"/> </Position14> <Position15> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="64" Column="13" TopLine="37"/> + <Filename Value="uutlListTest.pas"/> + <Caret Line="626" TopLine="610"/> </Position15> <Position16> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="77" TopLine="73"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="396" TopLine="380"/> </Position16> <Position17> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="69" Column="34" TopLine="48"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="397" TopLine="380"/> </Position17> <Position18> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="543" Column="26" TopLine="522"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="398" TopLine="380"/> </Position18> <Position19> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="544" Column="42" TopLine="522"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="402" TopLine="380"/> </Position19> <Position20> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="538" Column="23" TopLine="520"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="403" TopLine="380"/> </Position20> <Position21> - <Filename Value="..\uutlListBase.pas"/> - <Caret Line="33" Column="5" TopLine="15"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="405" TopLine="380"/> </Position21> <Position22> - <Filename Value="..\uutlListBase.pas"/> - <Caret Line="100" Column="8" TopLine="79"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="407" TopLine="381"/> </Position22> <Position23> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="557" Column="8" TopLine="536"/> + <Filename Value="uutlListTest.pas"/> + <Caret Line="627" TopLine="610"/> </Position23> <Position24> - <Filename Value="..\uutlGenerics.pas"/> - <Caret Line="753" Column="8" TopLine="732"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="103" TopLine="89"/> </Position24> <Position25> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="82" Column="18" TopLine="57"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="104" TopLine="89"/> </Position25> <Position26> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="97" TopLine="97"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="400" Column="28" TopLine="381"/> </Position26> <Position27> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="90" Column="27" TopLine="67"/> + <Filename Value="..\uutlEnumerator.pas"/> + <Caret Line="105" Column="24" TopLine="89"/> </Position27> <Position28> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="96" Column="21" TopLine="70"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="110" Column="29" TopLine="100"/> </Position28> <Position29> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="110" TopLine="107"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="106" TopLine="100"/> </Position29> <Position30> - <Filename Value="uutlEnumeratorTests.pas"/> - <Caret Line="640" Column="4" TopLine="616"/> + <Filename Value="..\uutlListBase.pas"/> + <Caret Line="113" Column="72" TopLine="100"/> </Position30> </JumpHistory> </ProjectSession> @@ -653,13 +665,10 @@ <InitialEnabled Value="False"/> </Item1> </BreakPointGroups> - <Watches Count="2"> + <Watches Count="1"> <Item1> - <Expression Value="p+i"/> + <Expression Value="fCurrent"/> </Item1> - <Item2> - <Expression Value="p + j"/> - </Item2> </Watches> </Debugging> </CONFIG> diff --git a/tests/uutlListTest.pas b/tests/uutlListTest.pas index 1f168d2..cd825e2 100644 --- a/tests/uutlListTest.pas +++ b/tests/uutlListTest.pas @@ -20,6 +20,9 @@ type fIntfList: TIntfList; fObjList: TObjList; + fEnumerator: TIntList.IutlEnumerator; + procedure AccessCurrentEnueratorItem; + protected procedure SetUp; override; procedure TearDown; override; @@ -48,12 +51,22 @@ type procedure AddRemoveInterfaces; procedure AddRemoveObject_OwnedByList; procedure AddRemoveObject_NotOwnedByList; + procedure AddItemWithinEnumeration; + procedure DeleteItemWithinEnumeration; end; implementation //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlListTest////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TutlListTest.AccessCurrentEnueratorItem; +var + i: Integer; +begin + i := fEnumerator.Current; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlListTest.SetUp; begin @@ -423,6 +436,256 @@ begin AssertEquals(0, IntfObjCounter); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TutlListTest.AddItemWithinEnumeration; + + procedure InitList; + var i: Integer; + begin + fIntList.Clear; + for i := 0 to 4 do + fIntList.Add(i); + end; + +var + e: TIntList.IutlEnumerator; +begin + e := fIntList.GetUtlEnumerator; + + // forward - insert behind current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + fIntList.Insert(2, 999); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(999, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertFalse (e.MoveNext); + + // forward - insert before current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + fIntList.Insert(1, 999); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertFalse (e.MoveNext); + + // forward - insert current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + fIntList.Insert(1, 999); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertFalse (e.MoveNext); + + {$IFDEF UTL_ENUMERATORS} + e := e.Reverse; + + // reverse - add after current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + fIntList.Insert(3, 999); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertFalse (e.MoveNext); + + // reverse - insert before current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + fIntList.Insert(2, 999); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(999, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertFalse (e.MoveNext); + + // reverse - insert current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + fIntList.Insert(3, 999); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(999, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertFalse (e.MoveNext); + {$ENDIF} +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TutlListTest.DeleteItemWithinEnumeration; + + procedure InitList; + var i: Integer; + begin + fIntList.Clear; + for i := 0 to 4 do + fIntList.Add(i); + end; + +var + e: TIntList.IutlEnumerator; +begin + e := fIntList.GetUtlEnumerator; + + // forward - delete behind current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + fIntList.Delete(2); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertFalse (e.MoveNext); + + // forward - delete before current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + fIntList.Remove(1); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertFalse (e.MoveNext); + + // forward - delete current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + fIntList.Remove(1); + fEnumerator := e; + AssertException('Current does not raise exception after deleting current', EInvalidOperation, @AccessCurrentEnueratorItem); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertFalse (e.MoveNext); + + {$IFDEF UTL_ENUMERATORS} + e := e.Reverse; + + // reverse - delete after current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + fIntList.Remove(4); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertFalse (e.MoveNext); + + // reverse - delete before current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + fIntList.Remove(2); + AssertEquals(3, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertFalse (e.MoveNext); + + // reverse - delete current + InitList; + e.Reset; + AssertTrue (e.MoveNext); + AssertEquals(4, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(3, e.Current); + fIntList.Remove(3); + fEnumerator := e; + AssertException('Current does not raise exception after deleting current', EInvalidOperation, @AccessCurrentEnueratorItem); + AssertTrue (e.MoveNext); + AssertEquals(2, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(1, e.Current); + AssertTrue (e.MoveNext); + AssertEquals(0, e.Current); + AssertFalse (e.MoveNext); + {$ENDIF} +end; + initialization RegisterTest(TutlListTest.Suite); diff --git a/tests/uutlObservableHashSetTests.pas b/tests/uutlObservableHashSetTests.pas index 126e040..d73a781 100644 --- a/tests/uutlObservableHashSetTests.pas +++ b/tests/uutlObservableHashSetTests.pas @@ -17,6 +17,7 @@ type fCaptureEvents: Boolean; fSet: TObservableIntSet; fEventArgs: TEventArgList; + fEventListener: IutlEventListener; procedure EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs); @@ -48,8 +49,9 @@ begin inherited SetUp; fCaptureEvents := false; fEventArgs := TEventArgList.Create(true); + fEventListener := TutlEventListenerCallback.Create(@EventHandler); fSet := TObservableIntSet.Create(true); - fSet.RegisterEventHandler(@EventHandler); + fSet.RegisterEventListener(fEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -57,6 +59,7 @@ procedure TutlObservableHashSetTests.TearDown; begin FreeAndNil(fSet); FreeAndNil(fEventArgs); + fEventListener := nil; inherited TearDown; end; diff --git a/tests/uutlObservableListTests.pas b/tests/uutlObservableListTests.pas index 92a308f..a5a24f0 100644 --- a/tests/uutlObservableListTests.pas +++ b/tests/uutlObservableListTests.pas @@ -17,6 +17,7 @@ type fCaptureEvents: Boolean; fList: TObservableIntList; fEventArgs: TEventArgList; + fEventListener: IutlEventListener; procedure EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs); @@ -48,8 +49,9 @@ begin inherited SetUp; fCaptureEvents := false; fEventArgs := TEventArgList.Create(true); + fEventListener := TutlEventListenerCallback.Create(@EventHandler); fList := TObservableIntList.Create(true); - fList.RegisterEventHandler(@EventHandler); + fList.RegisterEventListener(fEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -57,6 +59,7 @@ procedure TutlObservableListTests.TearDown; begin FreeAndNil(fList); FreeAndNil(fEventArgs); + fEventListener := nil; inherited TearDown; end; diff --git a/tests/uutlObservableMapTests.pas b/tests/uutlObservableMapTests.pas index f8ba8a9..cda99f4 100644 --- a/tests/uutlObservableMapTests.pas +++ b/tests/uutlObservableMapTests.pas @@ -17,6 +17,7 @@ type fCaptureEvents: Boolean; fMap: TObservableIntStringMap; fEventArgs: TEventArgList; + fEventListener: IutlEventListener; procedure EventHandler(constref aSender: TObject; constref aEventArgs: IutlEventArgs); @@ -48,8 +49,9 @@ begin inherited SetUp; fCaptureEvents := false; fEventArgs := TEventArgList.Create(true); + fEventListener := TutlEventListenerCallback.Create(@EventHandler); fMap := TObservableIntStringMap.Create(true, true); - fMap.RegisterEventHandler(@EventHandler); + fMap.RegisterEventListener(fEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -57,6 +59,7 @@ procedure TutlObservableMapTests.TearDown; begin FreeAndNil(fMap); FreeAndNil(fEventArgs); + fEventListener := nil; inherited TearDown; end; diff --git a/uutlCommon.pas b/uutlCommon.pas index a3e64fc..d5124c3 100644 --- a/uutlCommon.pas +++ b/uutlCommon.pas @@ -10,18 +10,23 @@ uses type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TutlInterfaceNoRefCount = class(TObject, IUnknown) + TutlInterfacedObject = class(TObject, IUnknown) protected - fRefCount: longint; + fRefCount: longint; + fAutoFree: Boolean; - { implement methods of IUnknown } - function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; - function _AddRef: longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual; - function _Release: longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual; + { implement methods of IUnknown } + function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; + function _AddRef: longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual; + function _Release: longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; virtual; public + property AutoFree: Boolean read fAutoFree write fAutoFree; property RefCount: LongInt read fRefCount; + + constructor Create; end; + TutlInterfaceNoRefCount = TutlInterfacedObject; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TutlCSVList = class(TStringList) @@ -295,9 +300,9 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TutlInterfaceNoRefCount/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TutlInterfacedObject/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TutlInterfaceNoRefCount.QueryInterface(constref iid: tguid; out obj): longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; +function TutlInterfacedObject.QueryInterface(constref iid: tguid; out obj): longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; begin if getinterface(iid,obj) then result:=S_OK @@ -306,15 +311,25 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TutlInterfaceNoRefCount._AddRef: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; +function TutlInterfacedObject._AddRef: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; begin result := InterLockedIncrement(fRefCount); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TutlInterfaceNoRefCount._Release: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; +function TutlInterfacedObject._Release: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; begin result := InterLockedDecrement(fRefCount); + if (result = 0) and fAutoFree then + Destroy; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TutlInterfacedObject.Create; +begin + inherited Create; + fAutoFree := false; + fRefCount := 0; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uutlComparer.pas b/uutlComparer.pas index 7c615f9..91de2cd 100644 --- a/uutlComparer.pas +++ b/uutlComparer.pas @@ -28,7 +28,7 @@ type generic TutlEqualityCompareEventN<T> = function(constref i1, i2: T): Boolean is nested; {$ENDIF} - generic TutlCalbackEqualityComparer<T> = class( + generic TutlCallbackEqualityComparer<T> = class( TInterfacedObject, specialize IutlEqualityComparer<T>) @@ -140,9 +140,9 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TutlCalbackEqualityComparer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TutlCallbackEqualityComparer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TutlCalbackEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean; +function TutlCallbackEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean; begin result := false; case fType of @@ -157,7 +157,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEvent); +constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEvent); begin inherited Create; fType := eetNormal; @@ -165,7 +165,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEventO); +constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEventO); begin inherited Create; fType := eetObject; @@ -174,7 +174,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// {$IFDEF UTL_NESTED_PROCVARS} -constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEventN); +constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEventN); begin inherited Create; fType := eetNested; diff --git a/uutlEnumerator.pas b/uutlEnumerator.pas index 2e06ba1..9a35cd7 100644 --- a/uutlEnumerator.pas +++ b/uutlEnumerator.pas @@ -97,6 +97,7 @@ type protected property Memory: PT read fMemory write fMemory; property Reversed: Boolean read fReversed write fReversed; + property Current: Integer read fCurrent write fCurrent; property First: Integer read fFirst write fFirst; property Last: Integer read fLast write fLast; diff --git a/uutlEvent.pas b/uutlEvent.pas index 2085df0..0b4fc3f 100644 --- a/uutlEvent.pas +++ b/uutlEvent.pas @@ -17,18 +17,18 @@ type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IutlEventListener = interface(IUnknown) ['{BC45E26B-96F7-4151-87F1-C330C8C668E5}'] - procedure DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); + procedure DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TutlEventHandler = procedure (constref aSender: TObject; constref aEvent: IutlEventArgs) of object; + TutlEventHandler = procedure (constref aSender: TObject; constref aEventArgs: IutlEventArgs) of object; TutlEventArgs = class(TInterfacedObject, IutlEventArgs); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - generic IutlObservable<T> = interface(specialize {$IFDEF UTL_ADVANCED_ENUMERATORS}IutlEnumerable{$ELSE}IEnumerable{$ENDIF}<T>) + IutlObservable = interface(IUnknown) ['{C54BD844-8273-4ACF-90C5-05DACF4359AF}'] - procedure RegisterEventHandler (const aHandler: TutlEventHandler); - procedure UnregisterEventHandler(const aHandler: TutlEventHandler); + procedure RegisterEventListener (const aListener: IutlEventListener); + procedure UnregisterEventListener(const aListener: IutlEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -45,6 +45,18 @@ type end; TutlNotifyEventList = specialize TutlEventList<TNotifyEvent>; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TutlEventHandlerList = class( + specialize TutlEventList<TutlEventHandler> + , IutlEventListener) + + public { IutlEventListener } + procedure DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); + + public + constructor Create; + end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TutlEventListenerSet = class( specialize TutlCustomHashSet<IutlEventListener> @@ -58,7 +70,7 @@ type end; public { IutlEventListener } - procedure DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); + procedure DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); public constructor Create; reintroduce; @@ -73,7 +85,7 @@ type fHandler: TutlEventHandler; public { IEventListener } - procedure DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); + procedure DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); public constructor Create(const aHandler: TutlEventHandler); @@ -100,7 +112,7 @@ type function PopEventPair(out aPair: TEventPair): Boolean; public { IEventListener } - procedure DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); + procedure DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); public function RegisterListener (const aListener: IutlEventListener): Boolean; @@ -109,7 +121,7 @@ type procedure DispatchEvents; constructor Create; - destructor Destroy; override; + destructor Destroy; override; end; implementation @@ -148,6 +160,24 @@ begin inherited Create(TComparer.Create, true); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TutlEventHandlerList/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TutlEventHandlerList.DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); +var + e: TutlEventHandler; +begin + for e in self do + e(aSender, aEventArgs); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TutlEventHandlerList.Create; +begin + inherited Create; + AutoFree := true; +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlEventListenerSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -170,12 +200,12 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlEventListenerSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlEventListenerSet.DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); +procedure TutlEventListenerSet.DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); var - l: IutlEventListener; + e: IutlEventListener; begin - for l in self do - l.DispatchEvent(aSender, aEvent); + for e in self do + e.DispatchEvent(aSender, aEventArgs); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -187,9 +217,9 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlEventListenerCallback////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlEventListenerCallback.DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); +procedure TutlEventListenerCallback.DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); begin - fHandler(aSender, aEvent); + fHandler(aSender, aEventArgs); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -228,12 +258,12 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlEventListenerAsync.DispatchEvent(constref aSender: TObject; constref aEvent: IutlEventArgs); +procedure TutlEventListenerAsync.DispatchEvent(constref aSender: TObject; constref aEventArgs: IutlEventArgs); var p: TEventPair; begin p.first := aSender; - p.second := aEvent; + p.second := aEventArgs; fEventLock.Enter; try fEvents.Add(p); diff --git a/uutlListBase.pas b/uutlListBase.pas index 76ff7bf..3138ce4 100644 --- a/uutlListBase.pas +++ b/uutlListBase.pas @@ -20,14 +20,25 @@ type IutlEnumerator = specialize IutlEnumerator<T>; private type + TEnumeratorAction = ( + eaAdded, + eaRemoved, + eaReallocated + ); + TEnumerator = class( specialize TutlMemoryEnumerator<T> , IEnumerator , IutlEnumerator) private fOwner: TutlListBase; + fCurrentIsInvalid: Boolean; + fNext: TEnumerator; + fPrev: TEnumerator; protected { IEnumerator } + function GetCurrent: T; override; + function InternalMoveNext: Boolean; override; procedure InternalReset; override; {$IFDEF UTL_ENUMERATORS} @@ -36,11 +47,18 @@ type {$ENDIF} public + procedure Update(const aIndex: Integer; const aAction: TEnumeratorAction); + constructor Create(const aOwner: TutlListBase; const aReversed: Boolean); reintroduce; + destructor Destroy; override; end; strict private fCount: Integer; + fFirstEnumerator: TEnumerator; + fLastEnumerator: TEnumerator; + + procedure UpdateEnumerator(const aIndex: Integer; const aAction: TEnumeratorAction); protected function GetCount: Integer; override; @@ -48,6 +66,7 @@ type function GetItem (const aIndex: Integer): T; virtual; procedure SetItem (const aIndex: Integer; aValue: T); virtual; + procedure SetCapacity (const aValue: integer); override; procedure InsertIntern(const aIndex: Integer; constref aValue: T); virtual; procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean); virtual; @@ -80,6 +99,21 @@ uses //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlListBase.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TutlListBase.TEnumerator.GetCurrent: T; +begin + if fCurrentIsInvalid then + raise EInvalidOperation.Create('current item was deleted, move on with ''MoveNext'' before accessing ''Current'''); + result := inherited GetCurrent; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TutlListBase.TEnumerator.InternalMoveNext: Boolean; +begin + result := inherited InternalMoveNext; + fCurrentIsInvalid := false; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlListBase.TEnumerator.InternalReset; begin @@ -99,17 +133,82 @@ begin end; {$ENDIF} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TutlListBase.TEnumerator.Update(const aIndex: Integer; const aAction: TEnumeratorAction); +begin + case aAction of + eaAdded: begin + if (aIndex <= Current) then + Current := Current + 1; + Last := Last + 1; + end; + + eaRemoved: begin + fCurrentIsInvalid := (aIndex = Current); + if (aIndex < Current) + or ( (aIndex = Current) + and not Reversed) + then + Current := Current - 1; + Last := Last - 1; + end; + + eaReallocated: begin + if (fOwner.Count > 0) + then Memory := fOwner.GetInternalItem(0) + else Memory := nil; + end; + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TutlListBase.TEnumerator.Create(const aOwner: TutlListBase; const aReversed: Boolean); begin if not Assigned(aOwner) then raise EArgumentNilException.Create('aOwner'); fOwner := aOwner; + if not Assigned(fOwner.fLastEnumerator) then begin + fPrev := nil; + fNext := nil; + fOwner.fFirstEnumerator := self; + fOwner.fLastEnumerator := self; + end else begin + fPrev := fOwner.fLastEnumerator; + fNext := nil; + fOwner.fLastEnumerator.fNext := self; + fOwner.fLastEnumerator := self; + end; inherited Create(nil, aReversed, 0, -1); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TutlListBase.TEnumerator.Destroy; +begin + if (fOwner.fFirstEnumerator = self) then + fOwner.fFirstEnumerator := fNext; + if (fOwner.fLastEnumerator = self) then + fOwner.fLastEnumerator := fPrev; + if Assigned(fPrev) then + fPrev.fNext := fNext; + if Assigned(fNext) then + fNext.fPrev := fPrev; + inherited Destroy; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlListBase////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TutlListBase.UpdateEnumerator(const aIndex: Integer; const aAction: TEnumeratorAction); +var + e: TEnumerator; +begin + e := fFirstEnumerator; + while Assigned(e) do begin + e.Update(aIndex, aAction); + e := e.fNext; + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlListBase.GetCount: Integer; begin @@ -144,6 +243,12 @@ begin p^ := aValue; end; +procedure TutlListBase.SetCapacity(const aValue: integer); +begin + inherited SetCapacity(aValue); + UpdateEnumerator(0, eaReallocated); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlListBase.InsertIntern(const aIndex: Integer; constref aValue: T); var @@ -158,6 +263,7 @@ begin System.Move(p^, (p+1)^, (fCount - aIndex) * SizeOf(T)); p^ := aValue; inc(fCount); + UpdateEnumerator(aIndex, eaAdded); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -174,6 +280,7 @@ begin if CanShrink and (Capacity > 128) and (fCount < Capacity shr 2) then // only 25% used SetCapacity(Capacity shr 1); // set to 50% Capacity FillByte(GetInternalItem(fCount)^, (Capacity-fCount) * SizeOf(T), 0); + UpdateEnumerator(aIndex, eaRemoved); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -183,7 +290,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TutlListBase.GetUtlEnumerator: specialize IutlEnumerator<T>; +function TutlListBase.GetUtlEnumerator: IutlEnumerator; begin result := TEnumerator.Create(self, false); end; diff --git a/uutlLogger.pas b/uutlLogger.pas index 80a5353..b2489c4 100644 --- a/uutlLogger.pas +++ b/uutlLogger.pas @@ -85,12 +85,12 @@ type private fStream: TFileStream; fAutoFlush: Boolean; - fAutoFree: Boolean; + procedure SetAutoFree(aValue: Boolean); - protected - function _Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; override; + protected procedure WriteLog(const aLogger: TutlLogger; const aTime: TDateTime; const aLevel: TutlLogLevel; const aSender: string; const aMessage: String); + public constructor Create(const aFilename: String; const aMode: TutlFileLoggerMode; const aAutoFree: Boolean = false); destructor Destroy; override; @@ -98,7 +98,6 @@ type procedure Flush(); overload; published property AutoFlush: Boolean read fAutoFlush write fAutoFlush; - property AutoFree: Boolean read fAutoFree write SetAutoFree; end; { TutlConsoleLogger } @@ -186,13 +185,6 @@ begin Free; end; -function TutlFileLogger._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF}; -begin - result := inherited _Release; - if (Result <= 0) and fAutoFree then - Free; -end; - procedure TutlFileLogger.WriteLog(const aLogger: TutlLogger; const aTime: TDateTime; const aLevel: TutlLogLevel; const aSender: string; const aMessage: String); var diff --git a/uutlObservable.pas b/uutlObservable.pas index 6ab422d..f63fbf8 100644 --- a/uutlObservable.pas +++ b/uutlObservable.pas @@ -54,10 +54,7 @@ type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// generic TutlObservableCustomList<T> = class( specialize TutlCustomList<T> - , specialize IutlObservable<T>) - - private type - TEventHandlerList = specialize TutlEventList<TutlEventHandler>; + , IutlObservable) public type TItemEventArgs = class(specialize TutlObservableItemEventArgs<T>) @@ -77,7 +74,7 @@ type end; private - fEventHandler: TEventHandlerList; + fEventListener: TutlEventListenerSet; protected procedure InsertIntern(const aIndex: Integer; constref aValue: T); override; @@ -89,8 +86,8 @@ type procedure DoClear (); virtual; public { IutlObservable } - procedure RegisterEventHandler (const aHandler: TutlEventHandler); - procedure UnregisterEventHandler(const aHandler: TutlEventHandler); + procedure RegisterEventListener(const aListener: IutlEventListener); + procedure UnregisterEventListener(const aListener: IutlEventListener); protected procedure SetItem(const aIndex: Integer; aValue: T); override; @@ -114,9 +111,9 @@ type end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - generic TutlObservableCustomHashSet<T> = class(specialize TutlCustomHashSet<T>) - private type - TEventHandlerList = specialize TutlEventList<TutlEventHandler>; + generic TutlObservableCustomHashSet<T> = class( + specialize TutlCustomHashSet<T> + , IutlObservable) public type TItemEventArgs = class(specialize TutlObservableItemEventArgs<T>) @@ -136,7 +133,7 @@ type end; private - fEventHandler: TEventHandlerList; + fEventListener: TutlEventListenerSet; protected procedure InsertIntern(const aIndex: Integer; constref aValue: T); override; @@ -149,8 +146,8 @@ type procedure DoClear (); virtual; public { IutlObservable } - procedure RegisterEventHandler (const aHandler: TutlEventHandler); - procedure UnregisterEventHandler(const aHandler: TutlEventHandler); + procedure RegisterEventListener(const aListener: IutlEventListener); + procedure UnregisterEventListener(const aListener: IutlEventListener); public procedure Clear; override; @@ -166,9 +163,9 @@ type end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - generic TutlObservableCustomMap<TKey, TValue> = class(specialize TutlCustomMap<TKey, TValue>) - private type - TEventHandlerList = specialize TutlEventList<TutlEventHandler>; + generic TutlObservableCustomMap<TKey, TValue> = class( + specialize TutlCustomMap<TKey, TValue> + , IutlObservable) public type TObservableHashSet = class(THashSet) @@ -207,7 +204,7 @@ type end; private - fEventHandler: TEventHandlerList; + fEventListener: TutlEventListenerSet; protected procedure DoAddItem (const aIndex: Integer; constref aKey: TKey; constref aItem: TValue); virtual; @@ -216,8 +213,8 @@ type procedure DoClear (); virtual; public { IutlObservable } - procedure RegisterEventHandler (const aHandler: TutlEventHandler); - procedure UnregisterEventHandler(const aHandler: TutlEventHandler); + procedure RegisterEventListener(const aListener: IutlEventListener); + procedure UnregisterEventListener(const aListener: IutlEventListener); public constructor Create(const aHashSet: TObservableHashSet; const aOwnsKeys: Boolean; const aOwnsValues: Boolean); reintroduce; @@ -310,66 +307,42 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomList.DoAddItem(const aIndex: Integer; constref aItem: T); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TItemEventArgs.Create(oetAdd, aIndex, aItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetAdd, aIndex, aItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomList.DoRemoveItem(const aIndex: Integer; constref aItem: T); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TItemEventArgs.Create(oetRemove, aIndex, aItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetRemove, aIndex, aItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomList.DoChangeItem(const aIndex: Integer; constref aOldItem: T; constref aNewItem: T); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomList.DoClear; -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TutlObservableEventArgs.Create(oetClear); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TutlObservableEventArgs.Create(oetClear)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlObservableCustomList.RegisterEventHandler(const aHandler: TutlEventHandler); +procedure TutlObservableCustomList.RegisterEventListener(const aListener: IutlEventListener); begin - fEventHandler.Add(aHandler); + fEventListener.Add(aListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlObservableCustomList.UnregisterEventHandler(const aHandler: TutlEventHandler); +procedure TutlObservableCustomList.UnregisterEventListener(const aListener: IutlEventListener); begin - fEventHandler.Remove(aHandler); + fEventListener.Remove(aListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -389,7 +362,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TutlObservableCustomList.Create(aEqualityComparer: IEqualityComparer; aOwnsObjects: Boolean); begin - fEventHandler := TEventHandlerList.Create; + fEventListener := TutlEventListenerSet.Create; inherited Create(aEqualityComparer, aOwnsObjects); end; @@ -397,7 +370,7 @@ end; destructor TutlObservableCustomList.Destroy; begin inherited Destroy; - FreeAndNil(fEventHandler); + FreeAndNil(fEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -458,66 +431,42 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomHashSet.DoAddItem(const aIndex: Integer; constref aItem: T); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TItemEventArgs.Create(oetAdd, aIndex, aItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetAdd, aIndex, aItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomHashSet.DoRemoveItem(const aIndex: Integer; constref aItem: T); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TItemEventArgs.Create(oetRemove, aIndex, aItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetRemove, aIndex, aItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomHashSet.DoChangeItem(const aIndex: Integer; constref aOldItem: T; constref aNewItem: T); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TReplaceEventArgs.Create(oetReplace, aIndex, aOldItem, aNewItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomHashSet.DoClear; -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TutlObservableEventArgs.Create(oetClear); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TutlObservableEventArgs.Create(oetClear)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlObservableCustomHashSet.RegisterEventHandler(const aHandler: TutlEventHandler); +procedure TutlObservableCustomHashSet.RegisterEventListener(const aListener: IutlEventListener); begin - fEventHandler.Add(aHandler); + fEventListener.Add(aListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlObservableCustomHashSet.UnregisterEventHandler(const aHandler: TutlEventHandler); +procedure TutlObservableCustomHashSet.UnregisterEventListener(const aListener: IutlEventListener); begin - fEventHandler.Remove(aHandler); + fEventListener.Remove(aListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -530,7 +479,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TutlObservableCustomHashSet.Create(const aComparer: IComparer; const aOwnsItems: Boolean); begin - fEventHandler := TEventHandlerList.Create; + fEventListener := TutlEventListenerSet.Create; inherited Create(aComparer, aOwnsItems); end; @@ -538,7 +487,7 @@ end; destructor TutlObservableCustomHashSet.Destroy; begin inherited Destroy; - FreeAndNil(fEventHandler); + FreeAndNil(fEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -627,15 +576,9 @@ procedure TutlObservableCustomMap.DoAddItem( const aIndex: Integer; constref aKey: TKey; constref aItem: TValue); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TItemEventArgs.Create(oetAdd, aIndex, aKey, aItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetAdd, aIndex, aKey, aItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -643,15 +586,9 @@ procedure TutlObservableCustomMap.DoRemoveItem( const aIndex: Integer; constref aKey: TKey; constref aItem: TValue); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TItemEventArgs.Create(oetRemove, aIndex, aKey, aItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TItemEventArgs.Create(oetRemove, aIndex, aKey, aItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -660,40 +597,28 @@ procedure TutlObservableCustomMap.DoChangeItem( constref aKey: TKey; constref aOldItem: TValue; constref aNewItem: TValue); -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TReplaceEventArgs.Create(oetReplace, aIndex, aKey, aOldItem, aNewItem); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TReplaceEventArgs.Create(oetReplace, aIndex, aKey, aOldItem, aNewItem)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TutlObservableCustomMap.DoClear; -var - args: IutlEventArgs; - e: TutlEventHandler; begin - if not Assigned(fEventHandler) or fEventHandler.IsEmpty then - exit; - args := TutlObservableEventArgs.Create(oetClear); - for e in fEventHandler do - e(self, args); + if Assigned(fEventListener) and not fEventListener.IsEmpty then + fEventListener.DispatchEvent(self, TutlObservableEventArgs.Create(oetClear)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlObservableCustomMap.RegisterEventHandler(const aHandler: TutlEventHandler); +procedure TutlObservableCustomMap.RegisterEventListener(const aListener: IutlEventListener); begin - fEventHandler.Add(aHandler); + fEventListener.Add(aListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TutlObservableCustomMap.UnregisterEventHandler(const aHandler: TutlEventHandler); +procedure TutlObservableCustomMap.UnregisterEventListener(const aListener: IutlEventListener); begin - fEventHandler.Remove(aHandler); + fEventListener.Remove(aListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -702,7 +627,7 @@ constructor TutlObservableCustomMap.Create( const aOwnsKeys: Boolean; const aOwnsValues: Boolean); begin - fEventHandler := TEventHandlerList.Create; + fEventListener := TutlEventListenerSet.Create; inherited Create(aHashSet, aOwnsKeys, aOwnsValues); end; @@ -710,7 +635,7 @@ end; destructor TutlObservableCustomMap.Destroy; begin inherited Destroy; - FreeAndNil(fEventHandler); + FreeAndNil(fEventListener); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uutlSyncObjs.pas b/uutlSyncObjs.pas index 88e61b0..2f69960 100644 --- a/uutlSyncObjs.pas +++ b/uutlSyncObjs.pas @@ -9,6 +9,13 @@ uses uutlGenerics; type +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + IutlLockable = interface(IUnknown) + ['{CF01F747-D6A9-405B-8A8D-AC148FA9DABB}'] + procedure Lock; + procedure Unlock; + end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TutlCheckSynchronizeEvent = class(TObject) private @@ -85,7 +92,7 @@ type function LockedObject: T; inline; constructor Create(const aLock: TCriticalSection; const aObject: T); - destructor Destroy; override; + destructor Destroy; override; end; implementation