Core: docs

git-svn-id: svn://ultimatepp.org/upp/trunk@13586 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2019-09-05 12:53:06 +00:00
parent bff56d89b5
commit cabfb398c8

View file

@ -26,6 +26,7 @@ topic "U++ Core Tutorial";
[s2;%% U`+`+ Core Tutorial&]
[s22; Table of contents&]
[s0;3 &]
[s0;3 &]
[s0; [^`#Chapter`_1^ 1. Basics]&]
[s0; ___[^`#Section`_1`_1^ 1.1 Logging]&]
[s0; ___[^`#Section`_1`_2^ 1.2 String]&]
@ -80,7 +81,7 @@ topic "U++ Core Tutorial";
[s0; ___[^`#Section`_7`_4^ 7.4 CoWork]&]
[s0; ___[^`#Section`_7`_5^ 7.5 AsyncWork]&]
[s0; ___[^`#Section`_7`_6^ 7.6 CoPartition]&]
[s0; ___[^`#Section`_7`_7^ 7.7 CoWork loop method]&]
[s0; ___[^`#Section`_7`_7^ 7.7 CoDo]&]
[s0; ___[^`#Section`_7`_8^ 7.8 Parallel algorithms]&]
[s22;:Chapter`_1: 1. Basics&]
[s3;:Section`_1`_1: 1.1 Logging&]
@ -124,9 +125,9 @@ variable name and value:&]
[s7; DUMPHEX(h);&]
[s0; &]
[s17; x `= 0x7b&]
[s17; h `= Memory at 0x00000084D9F1FC30, size 0x3 `= 3&]
[s17; `+0 0x00000084D9F1FC30 66 6F 6F
foo &]
[s17; h `= Memory at 0x025BFCF8, size 0x3 `= 3&]
[s17; `+0 0x025BFCF8 66 6F 6F
foo &]
[s0; &]
[s5; To log the value of a container (or generic Range), you can
either use normal [*C@5 LOG] / [*C@5 DUMP]:&]
@ -369,9 +370,9 @@ data, including zeroes:&]
[s7; &]
[s7; DUMPHEX(a);&]
[s0; &]
[s17; a `= Memory at 0x00000084D9F1FB90, size 0x5 `= 5&]
[s17; `+0 0x00000084D9F1FB90 31 32 33 34 00
1234. &]
[s17; a `= Memory at 0x025BFD58, size 0x5 `= 5&]
[s17; `+0 0x025BFD58 31 32 33 34 00
1234. &]
[s0; &]
[s3;H4;:Section`_1`_3: 1.3 StringBuffer&]
[s5; If you need a direct write access to [*C@5 String]`'s C`-string
@ -473,7 +474,7 @@ concrete types.&]
[s7; &]
[s7; DUMP(date);&]
[s0; &]
[s17; date `= 07/08/2018&]
[s17; date `= 09/05/2019&]
[s0; &]
[s5; All data members of [*C@5 Date] structure are public:&]
[s0; &]
@ -483,9 +484,9 @@ date members&]
would log&]
[s7; DUMP((int)date.day); // as characters&]
[s0; &]
[s17; (int)date.year `= 2018&]
[s17; (int)date.month `= 7&]
[s17; (int)date.day `= 8&]
[s17; (int)date.year `= 2019&]
[s17; (int)date.month `= 9&]
[s17; (int)date.day `= 5&]
[s0; &]
[s5; Dates can be compared:&]
[s0; &]
@ -500,15 +501,15 @@ ing goes to the next/previous day:&]
[s7; DUMP(`-`-date);&]
[s7; DUMP(`+`+date);&]
[s0; &]
[s17; date `+ 1 `= 07/09/2018&]
[s17; `-`-date `= 07/07/2018&]
[s17; `+`+date `= 07/08/2018&]
[s17; date `+ 1 `= 09/06/2019&]
[s17; `-`-date `= 09/04/2019&]
[s17; `+`+date `= 09/05/2019&]
[s0; &]
[s5; Subtraction of dates yields a number of days between them:&]
[s0; &]
[s7; DUMP(date `- Date(2000, 1, 1));&]
[s0; &]
[s17; date `- Date(2000, 1, 1) `= 6763&]
[s17; date `- Date(2000, 1, 1) `= 7187&]
[s0; &]
[s5; There are several [*C@5 Date] and calendar related functions:&]
[s0; &]
@ -534,7 +535,7 @@ ing goes to the next/previous day:&]
[s0; &]
[s7; DUMP(DayOfWeek(date)); // 0 is Sunday&]
[s0; &]
[s17; DayOfWeek(date) `= 0&]
[s17; DayOfWeek(date) `= 4&]
[s0; &]
[s0; &]
[s7; DUMP(LastDayOfMonth(date));&]
@ -544,11 +545,11 @@ ing goes to the next/previous day:&]
[s7; DUMP(DayOfYear(date)); // number of days since Jan`-1 `+ 1&]
[s7; DUMP(DayOfYear(Date(2016, 1, 1)));&]
[s0; &]
[s17; LastDayOfMonth(date) `= 07/31/2018&]
[s17; FirstDayOfMonth(date) `= 07/01/2018&]
[s17; LastDayOfYear(date) `= 12/31/2018&]
[s17; FirstDayOfYear(date) `= 01/01/2018&]
[s17; DayOfYear(date) `= 189&]
[s17; LastDayOfMonth(date) `= 09/30/2019&]
[s17; FirstDayOfMonth(date) `= 09/01/2019&]
[s17; LastDayOfYear(date) `= 12/31/2019&]
[s17; FirstDayOfYear(date) `= 01/01/2019&]
[s17; DayOfYear(date) `= 248&]
[s17; DayOfYear(Date(2016, 1, 1)) `= 1&]
[s0; &]
[s0; &]
@ -559,10 +560,10 @@ between two dates&]
partial months`' between two dates&]
[s7; DUMP(AddYears(date, 2));&]
[s0; &]
[s17; AddMonths(date, 20) `= 03/08/2020&]
[s17; AddMonths(date, 20) `= 05/05/2021&]
[s17; GetMonths(date, date `+ 100) `= 3&]
[s17; GetMonthsP(date, date `+ 100) `= 4&]
[s17; AddYears(date, 2) `= 07/08/2020&]
[s17; AddYears(date, 2) `= 09/05/2021&]
[s0; &]
[s0; &]
[s7; DUMP(GetWeekDate(2015, 1));&]
@ -602,11 +603,11 @@ time:&]
[s7; DUMP((int)time.minute);&]
[s7; DUMP((int)time.second);&]
[s0; &]
[s17; time `= 07/08/2018 09:28:56&]
[s17; (Date)time `= 07/08/2018&]
[s17; (int)time.hour `= 9&]
[s17; (int)time.minute `= 28&]
[s17; (int)time.second `= 56&]
[s17; time `= 09/05/2019 14:48:55&]
[s17; (Date)time `= 09/05/2019&]
[s17; (int)time.hour `= 14&]
[s17; (int)time.minute `= 48&]
[s17; (int)time.second `= 55&]
[s0; &]
[s5; Times can be compared:&]
[s0; &]
@ -633,10 +634,10 @@ but numbers represent seconds (using [*C@5 int64] datatype):&]
is in days&]
[s7; DUMP(time `- ToTime(date)); // Time `- Time is in seconds&]
[s0; &]
[s17; time `+ 1 `= 07/08/2018 09:28:57&]
[s17; time `+ 24 `* 3600 `= 07/09/2018 09:28:56&]
[s17; time `+ 1 `= 09/05/2019 14:48:56&]
[s17; time `+ 24 `* 3600 `= 09/06/2019 14:48:55&]
[s17; time `- date `= 0&]
[s17; time `- ToTime(date) `= 34136&]
[s17; time `- ToTime(date) `= 53335&]
[s0; &]
[s5; [*C@5 Time] defines era limits too:&]
[s0; &]
@ -691,9 +692,9 @@ items predefined by U`+`+:&]
[s7; DUMP(LoadFile(ConfigFile(`"test.txt`")));&]
[s7; DUMP(sout);&]
[s0; &]
[s17; LoadFile(ConfigFile(`"test.txt`")) `= 1.23 07/08/2018 07/08/2018
09:28:56&]
[s17; sout `= 1.23 07/08/2018 07/08/2018 09:28:56&]
[s17; LoadFile(ConfigFile(`"test.txt`")) `= 1.23 09/05/2019 09/05/2019
14:48:55&]
[s17; sout `= 1.23 09/05/2019 09/05/2019 14:48:55&]
[s0; &]
[s5; Getting client types involved into this schema is not too difficult,
all you need to do is to add [*C@5 ToString] method:&]
@ -752,14 +753,14 @@ too:&]
[s7; &]
[s7; DUMP(GetHashValue(x));&]
[s0; &]
[s17; GetHashValue(x) `= 4272824901&]
[s17; GetHashValue(x) `= 749369797&]
[s0; &]
[s0; &]
[s7; x.a << `'!`';&]
[s7; &]
[s7; DUMP(GetHashValue(x));&]
[s0; &]
[s17; GetHashValue(x) `= 3378606405&]
[s17; GetHashValue(x) `= 1076203717&]
[s0; &]
[s3;H4;:Section`_1`_8: 1.8 SgnCompare and CombineCompare&]
[s5; Traditional approach of C language of representing comparison
@ -1068,10 +1069,9 @@ in both little`-endian and big`-endian modes:&]
[s7; ss.Put32be(0x12345678);&]
[s7; DUMPHEX(ss.GetResult());&]
[s0; &]
[s17; ss.GetResult() `= Memory at 0x00000084D9F1F990, size 0x8 `=
8&]
[s17; `+0 0x00000084D9F1F990 78 56 34 12 12 34 56 78
xV4..4Vx &]
[s17; ss.GetResult() `= Memory at 0x025BF828, size 0x8 `= 8&]
[s17; `+0 0x025BF828 78 56 34 12 12 34 56 78
xV4..4Vx &]
[s0; &]
[s0; &]
[s7; StringStream ss2(ss.GetResult());&]
@ -1119,12 +1119,12 @@ them via [*C@5 Out] virtual method:&]
[s7; os << `"This is a test `" << 12345;&]
[s7; os.Close();&]
[s0; &]
[s17; String((const char `*)data, size) `= Memory at 0x000001E4641A1AE0,
size 0x14 `= 20&]
[s17; `+0 0x000001E4641A1AE0 54 68 69 73 20 69 73 20 61 20 74
65 73 74 20 31 This is a test 1&]
[s17; `+16 0x000001E4641A1AF0 32 33 34 35
2345 &]
[s17; String((const char `*)data, size) `= Memory at 0x0750F7D0, size
0x14 `= 20&]
[s17; `+0 0x0750F7D0 54 68 69 73 20 69 73 20 61 20 74 65 73 74
20 31 This is a test 1&]
[s17; `+16 0x0750F7E0 32 33 34 35
2345 &]
[s0; &]
[s5; [*C@5 TeeStream] sends output data to two separate streams:&]
[s0; &]
@ -1147,12 +1147,12 @@ block to stream data:&]
[s7; while(!ms.IsEof())&]
[s7; -|DUMPHEX(ms.GetLine());&]
[s0; &]
[s17; ms.GetLine() `= Memory at 0x00000084D9F1F5F8, size 0x9 `= 9&]
[s17; `+0 0x00000084D9F1F5F8 53 6F 6D 65 20 6C 69 6E 65
Some line &]
[s17; ms.GetLine() `= Memory at 0x00000084D9F1F5F8, size 0xC `= 12&]
[s17; `+0 0x00000084D9F1F5F8 41 6E 6F 74 68 65 72 20 6C 69 6E
65 Another line &]
[s17; ms.GetLine() `= Memory at 0x025BF6AC, size 0x9 `= 9&]
[s17; `+0 0x025BF6AC 53 6F 6D 65 20 6C 69 6E 65
Some line &]
[s17; ms.GetLine() `= Memory at 0x025BF6AC, size 0xC `= 12&]
[s17; `+0 0x025BF6AC 41 6E 6F 74 68 65 72 20 6C 69 6E 65
Another line &]
[s0; &]
[s3;H4;:Section`_2`_3: 2.3 Binary serialization&]
[s5; Serialization is a mechanism that converts structured data to/from
@ -1264,7 +1264,7 @@ original [*C@5 MyFoo], we can branch on previously stored [*C@5 version]:&]
[s7; DUMP(foo3.number);&]
[s7; DUMP(foo3.color);&]
[s0; &]
[s17; foo3.number `= 1679266384&]
[s17; foo3.number `= 0&]
[s17; foo3.color `= Color(Null)&]
[s0; &]
[s5; Note: [*C@5 operator/] is Stream method with several overloads
@ -1396,7 +1396,7 @@ to this value.&]
[s7; &]
[s7; DUMP(v);&]
[s0; &]
[s17; v `= `[1026, 994, 1000, 1042, 989, 947, 1008, 957, 1004, 1033`]&]
[s17; v `= `[986, 977, 1018, 957, 1004, 1023, 986, 992, 996, 1061`]&]
[s0; &]
[s5; Referencing invalid index is undefined operation. Sometimes
however it is useful to return the element value if index is
@ -1407,7 +1407,7 @@ with two parameter Get method:&]
[s7; DUMP(v.Get(`-10, 0));&]
[s7; DUMP(v.Get(13, `-1));&]
[s0; &]
[s17; v.Get(4, 0) `= 989&]
[s17; v.Get(4, 0) `= 1004&]
[s17; v.Get(`-10, 0) `= 0&]
[s17; v.Get(13, `-1) `= `-1&]
[s0; &]
@ -1417,7 +1417,7 @@ with two parameter Get method:&]
[s7; &]
[s7; DUMP(v);&]
[s0; &]
[s17; v `= `[947, 957, 989, 994, 1000, 1004, 1008, 1026, 1033, 1042`]&]
[s17; v `= `[957, 977, 986, 986, 992, 996, 1004, 1018, 1023, 1061`]&]
[s0; &]
[s3;H4;:Section`_3`_3: 3.3 Transfer issues&]
[s5; Often you need to pass content of one container to another of
@ -1523,15 +1523,15 @@ to it:&]
[s7; DUMPC(dist);&]
[s0; &]
[s17; dist:&]
[s17; -|`[0`] `= Test 5: `[2079, 1931, 2027, 1987, 1976`]&]
[s17; -|`[1`] `= Test 6: `[1710, 1676, 1687, 1653, 1609, 1665`]&]
[s17; -|`[2`] `= Test 7: `[1465, 1366, 1421, 1430, 1459, 1441, 1418`]&]
[s17; -|`[3`] `= Test 8: `[1233, 1288, 1268, 1238, 1271, 1290, 1205,
1207`]&]
[s17; -|`[4`] `= Test 9: `[1059, 1117, 1104, 1110, 1100, 1165, 1100,
1091, 1154`]&]
[s17; -|`[5`] `= Test 10: `[1003, 963, 940, 1018, 1041, 1020, 987, 1033,
1012, 983`]&]
[s17; -|`[0`] `= Test 5: `[1986, 2026, 1997, 2016, 1975`]&]
[s17; -|`[1`] `= Test 6: `[1632, 1655, 1692, 1633, 1677, 1711`]&]
[s17; -|`[2`] `= Test 7: `[1441, 1397, 1423, 1502, 1423, 1393, 1421`]&]
[s17; -|`[3`] `= Test 8: `[1245, 1276, 1280, 1252, 1247, 1222, 1197,
1281`]&]
[s17; -|`[4`] `= Test 9: `[1132, 1146, 1139, 1135, 1070, 1138, 1092,
1050, 1098`]&]
[s17; -|`[5`] `= Test 10: `[999, 1083, 934, 909, 983, 1013, 1031, 1048,
975, 1025`]&]
[s0; &]
[s5; Another possibility is to use [*C@5 Vector`::Add(T`&`&)] method,
which uses pick`-constructor instead of deep`-copy constructor.
@ -1776,8 +1776,8 @@ but make it invisible for [*C@5 Find] operation:&]
[s7; DUMP(ndx);&]
[s7; DUMP(ndx.Find(`"foo`"));&]
[s0; &]
[s17; ndx `= `[alfa, alfa, foo, delta, kappa, one, two, three`]&]
[s17; ndx.Find(`"foo`") `= 2&]
[s17; ndx `= `[alfa, alfa, gamma, delta, foo, one, two, three`]&]
[s17; ndx.Find(`"foo`") `= 4&]
[s0; &]
[s5; You can also remove all unlinked elements from [*C@5 Index] using
[*C@5 Sweep] method:&]
@ -1786,7 +1786,7 @@ but make it invisible for [*C@5 Find] operation:&]
[s7; &]
[s7; DUMP(ndx);&]
[s0; &]
[s17; ndx `= `[alfa, alfa, foo, delta, one, two, three`]&]
[s17; ndx `= `[alfa, alfa, delta, foo, one, two, three`]&]
[s0; &]
[s5; Operations directly removing or inserting elements of Index
are expensive, but available too:&]
@ -1795,21 +1795,21 @@ are expensive, but available too:&]
[s7; &]
[s7; DUMP(ndx);&]
[s0; &]
[s17; ndx `= `[alfa, foo, delta, one, two, three`]&]
[s17; ndx `= `[alfa, delta, foo, one, two, three`]&]
[s0; &]
[s0; &]
[s7; ndx.RemoveKey(`"two`");&]
[s7; &]
[s7; DUMP(ndx);&]
[s0; &]
[s17; ndx `= `[alfa, foo, delta, one, three`]&]
[s17; ndx `= `[alfa, delta, foo, one, three`]&]
[s0; &]
[s0; &]
[s7; ndx.Insert(0, `"insert`");&]
[s7; &]
[s7; DUMP(ndx);&]
[s0; &]
[s17; ndx `= `[insert, alfa, foo, delta, one, three`]&]
[s17; ndx `= `[insert, alfa, delta, foo, one, three`]&]
[s0; &]
[s5; PickKeys operation allows you to obtain Vector of elements of
Index in low constant time operation (while destroying source
@ -1819,7 +1819,7 @@ Index)&]
[s7; &]
[s7; DUMP(d);&]
[s0; &]
[s17; d `= `[insert, alfa, foo, delta, one, three`]&]
[s17; d `= `[insert, alfa, delta, foo, one, three`]&]
[s0; &]
[s5; Pick`-assigning [*C@5 Vector] to [*C@5 Index] is supported as well:&]
[s0; &]
@ -1829,7 +1829,7 @@ Index)&]
[s7; &]
[s7; DUMP(ndx);&]
[s0; &]
[s17; ndx `= `[test, alfa, foo, delta, one, three`]&]
[s17; ndx `= `[test, alfa, delta, foo, one, three`]&]
[s0; &]
[s3;H4;:Section`_3`_9: 3.9 Index and client types&]
[s5; In order to store elements to [*C@5 Index], they type must be
@ -2026,8 +2026,8 @@ you can iterate them using [*C@5 FindNext] method:&]
[s7; &]
[s7; DUMP(m);&]
[s0; &]
[s17; m `= `{1: John Smith, 22: Ali Baba, 3: Peter Carpenter, 44: Ivan
Wilks`}&]
[s17; m `= `{1: John Smith, 44: Ivan Wilks, 3: Peter Carpenter, 22: Ali
Baba`}&]
[s0; &]
[s5; [*C@5 PickValues] / [*C@5 PickIndex] / [*C@5 PickKeys] / pick internal
[*C@5 Vector] / [*C@5 Index] / [*C@5 Vector] of [*C@5 Index]:&]
@ -2039,8 +2039,8 @@ Wilks`}&]
[s7; DUMP(ks);&]
[s7; DUMP(m);&]
[s0; &]
[s17; ps `= `[John Smith, Ali Baba, Peter Carpenter, Ivan Wilks`]&]
[s17; ks `= `[1, 22, 3, 44`]&]
[s17; ps `= `[John Smith, Ivan Wilks, Peter Carpenter, Ali Baba`]&]
[s17; ks `= `[1, 44, 3, 22`]&]
[s17; m `= `{`}&]
[s0; &]
[s5; [*C@5 VectorMap] pick constructor to create map by picking:&]
@ -2051,8 +2051,8 @@ Wilks`}&]
[s7; &]
[s7; DUMP(m);&]
[s0; &]
[s17; m `= `{Changed key: John Smith, 22: Ali Baba, 3: Peter Carpenter,
44: Ivan Wilks`}&]
[s17; m `= `{Changed key: John Smith, 44: Ivan Wilks, 3: Peter Carpenter,
22: Ali Baba`}&]
[s0; &]
[s5; [*C@5 ArrayMap] is composition of Index and Array, for cases where
Array is better fit for value type (e.g. they are polymorphic):&]
@ -2280,7 +2280,7 @@ so does [*C@5 Tuple]:&]
[s0; &]
[s7; DUMP(GetHashValue(x));&]
[s0; &]
[s17; GetHashValue(x) `= 834842890&]
[s17; GetHashValue(x) `= 2387239184&]
[s0; &]
[s5; As long as individual types have defined [*C@5 operator`=`=],
[*C@5 Tuple] has defined [*C@5 operator`=`=] and [*C@5 operator!`=]:&]
@ -2434,11 +2434,11 @@ easier:&]
[s0; &]
[s17; typeid(ValueTypeOf<decltype(x)>).name() `= int&]
[s17; typeid(ValueTypeOf<decltype(SubRange(x, 1, 1))>).name() `= int&]
[s17; typeid(IteratorOf<decltype(x)>).name() `= int `* `_`_ptr64&]
[s17; typeid(IteratorOf<decltype(x)>).name() `= int `*&]
[s17; typeid(ConstIteratorOf<decltype(SubRange(x, 1, 1))>).name()
`= int `* `_`_ptr64&]
`= int `*&]
[s17; typeid(SubRangeOf<Vector<int>>).name() `= class Upp`::SubRangeClass<int
`* `_`_ptr64>&]
`*>&]
[s0; &]
[s5; While containers themselves and SubRange are the two most common
range types, U`+`+ has two special ranges. [*C@5 ConstRange] simply
@ -2690,11 +2690,11 @@ is for the most part seamless:&]
[s0; &]
[s17; a `= 1&]
[s17; b `= 2.34&]
[s17; c `= 07/08/2018&]
[s17; c `= 09/05/2019&]
[s17; d `= hello&]
[s17; x `= 1&]
[s17; y `= 2.34&]
[s17; z `= 07/08/2018&]
[s17; z `= 09/05/2019&]
[s17; s `= hello&]
[s0; &]
[s5; As for primitive types, Value seamlessly works with [*C@5 int],
@ -2726,7 +2726,7 @@ as it is supported by these types):&]
[s0; &]
[s17; i `= 1&]
[s17; j `= 2&]
[s17; k `= 07/08/2018 00:00:00&]
[s17; k `= 09/05/2019 00:00:00&]
[s17; t `= hello&]
[s0; &]
[s5; To determine type of value stored in [*C@5 Value], you can use
@ -3353,16 +3353,16 @@ thread to [*C@5 Wait] for its completion:&]
[s0; &]
[s17; In the main thread 0&]
[s17; In the thread 0&]
[s17; In the main thread 1&]
[s17; In the thread 1&]
[s17; In the main thread 2&]
[s17; In the main thread 1&]
[s17; In the thread 2&]
[s17; In the main thread 3&]
[s17; In the main thread 2&]
[s17; In the thread 3&]
[s17; In the main thread 4&]
[s17; In the main thread 3&]
[s17; In the thread 4&]
[s17; About to wait for thread to finish&]
[s17; In the main thread 4&]
[s17; In the thread 5&]
[s17; About to wait for thread to finish&]
[s17; In the thread 6&]
[s17; In the thread 7&]
[s17; In the thread 8&]
@ -3410,7 +3410,7 @@ code demonstrates why:&]
[s7; t.Wait();&]
[s7; DUMP(sum);&]
[s0; &]
[s17; sum `= 1031062&]
[s17; sum `= 1041445&]
[s0; &]
[s5; While the expected value is 2000000, produced value is different.
The problem is that both thread read / modify / write [*C@5 sum]
@ -3536,12 +3536,12 @@ testing data&]
[s0; &]
[s17; w `= `[Lorem, ipsum, dolor, sit, amet, consectetur, adipiscing,
elit, aliqua, Ut, enim, ad, minim, veniam, quis, nostrud, exercitation,
sed, do, eiusmod, tempor, incididunt, ut, labore, et, dolore,
magna, ullamco, laboris, nisi, aliquip, ex, ea, commodo, consequat,
esse, cillum, eu, fugiat, nulla, pariatur, Excepteur, officia,
esse, cillum, dolore, eu, fugiat, nulla, pariatur, Excepteur,
ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo, consequat,
Duis, aute, irure, in, reprehenderit, voluptate, velit, officia,
deserunt, mollit, anim, id, est, laborum, sint, occaecat, cupidatat,
non, proident, sunt, in, culpa, qui, Duis, aute, irure, reprehenderit,
voluptate, velit`]&]
non, proident, sunt, culpa, qui, sed, do, eiusmod, tempor, incididunt,
labore, et, magna`]&]
[s0; &]
[s5; Adding words to [*C@5 w] requires [*C@5 Mutex]. Alternative to this
`'result gathering`' [*C@5 Mutex] is [*C@5 CoWork`::FinLock]. The
@ -3570,12 +3570,12 @@ end of CoWork job&]
[s0; &]
[s17; w `= `[Lorem, ipsum, dolor, sit, amet, consectetur, adipiscing,
elit, aliqua, Ut, enim, ad, minim, veniam, quis, nostrud, exercitation,
sed, do, eiusmod, tempor, incididunt, ut, labore, et, dolore,
magna, ullamco, laboris, nisi, aliquip, ex, ea, commodo, consequat,
esse, cillum, eu, fugiat, nulla, pariatur, Excepteur, officia,
esse, cillum, dolore, eu, fugiat, nulla, pariatur, Excepteur,
ullamco, laboris, nisi, ut, aliquip, ex, ea, commodo, consequat,
Duis, aute, irure, in, reprehenderit, voluptate, velit, officia,
deserunt, mollit, anim, id, est, laborum, sint, occaecat, cupidatat,
non, proident, sunt, in, culpa, qui, Duis, aute, irure, reprehenderit,
voluptate, velit`]&]
non, proident, sunt, culpa, qui, sed, do, eiusmod, tempor, incididunt,
labore, et, magna`]&]
[s0; &]
[s5; Of course, the code performed after [*C@5 FinLock] should not
take long, otherwise there is negative impact on all [*C@5 CoWork]
@ -3639,6 +3639,14 @@ be checked in job routine using [*C@5 CoWork`::IsCanceled]:&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s17; Job was canceled&]
[s0; &]
[s5; Canceling CoWork is common in GUI applications.&]
[s3;H4;:Section`_7`_5: 7.5 [C@5 AsyncWork]&]
@ -3766,16 +3774,14 @@ h) `{&]
[s0; &]
[s17; sum `= 49995000&]
[s0; &]
[s3;H4;:Section`_7`_7: 7.7 CoWork loop method&]
[s5; An alternative to [*C@5 CoPartition] is `'loop`' method of [*C@5 CoWork]
([*C@5 Loop] method with synonym [*C@5 operator`*]). In this pattern,
[s3;H4;:Section`_7`_7: 7.7 CoDo&]
[s5; An alternative to [*C@5 CoPartition] is [*C@5 CoDo]. In this pattern,
the job is simply started in all threads and the code is responsible
for scheduling the work. [*C@5 Loop] / [*C@5 operator`*] waits for
all started threads to finish. For scheduling, it is possible
to use internal [*C@5 CoWork] index counter, which is set to 0
at the start of [*C@5 Loop] / [*C@5 operator`*]. This way, the overhead
associated with creating lambdas and scheduling them is kept
to the minimum.&]
for scheduling the work. [*C@5 CoDo] waits for all started threads
to finish. Scheduling is the responsibility of client code, but
can be easily managed using the std`::atomic counter. This way,
the overhead associated with creating lambdas and scheduling
them is kept to the minimum (basically the cost of atomic increment).&]
[s0; &]
[s7; Vector<String> data;&]
[s7; for(int i `= 0; i < 100; i`+`+)&]
@ -3783,15 +3789,15 @@ to the minimum.&]
[s7; &]
[s7; double sum `= 0;&]
[s7; &]
[s7; CoWork co;&]
[s7; co `* `[`&`] `{&]
[s7; -|int i;&]
[s7; std`::atomic<int> ii `= 0;&]
[s7; &]
[s7; CoDo(`[`&`] `{&]
[s7; -|double m `= 0;&]
[s7; -|while((i `= co.Next()) < data.GetCount())&]
[s7; -|for(int i `= ii`+`+; i < data.GetCount(); i `= ii`+`+)&]
[s7; -|-|m `+`= atof(data`[i`]);&]
[s7; -|CoWork`::FinLock();&]
[s7; -|sum `+`= m;&]
[s7; `};&]
[s7; `});&]
[s7; &]
[s7; DUMP(sum);&]
[s0; &]