.tutorial

git-svn-id: svn://ultimatepp.org/upp/trunk@11670 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-01-08 09:47:49 +00:00
parent 812dd38427
commit 4408e2f4e2
2 changed files with 107 additions and 75 deletions

View file

@ -80,8 +80,9 @@ 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 Parallel algorithms]&]
[s0;^`#Section`_7`_7^ &]
[s0; ___[^`#Section`_7`_7^ 7.7 CoWork loop method]&]
[s0; ___[^`#Section`_7`_8^ 7.8 Parallel algorithms]&]
[s0;^`#Section`_7`_8^ &]
[s22;:Chapter`_1: 1. Basics&]
[s3;:Section`_1`_1: 1.1 Logging&]
[s5; Logging is a useful technique to trace the flow of the code
@ -124,8 +125,8 @@ variable name and value:&]
[s7; DUMPHEX(h);&]
[s0; &]
[s17; x `= 0x7b&]
[s17; h `= Memory at 0x01FEF7A0, size 0x3 `= 3&]
[s17; `+0 0x01FEF7A0 66 6F 6F
[s17; h `= Memory at 0x0218FDB4, size 0x3 `= 3&]
[s17; `+0 0x0218FDB4 66 6F 6F
foo &]
[s0; &]
[s5; To log the value of a container (or generic Range), you can
@ -369,8 +370,8 @@ data, including zeroes:&]
[s7; &]
[s7; DUMPHEX(a);&]
[s0; &]
[s17; a `= Memory at 0x01FEF800, size 0x5 `= 5&]
[s17; `+0 0x01FEF800 31 32 33 34 00
[s17; a `= Memory at 0x0218FE14, size 0x5 `= 5&]
[s17; `+0 0x0218FE14 31 32 33 34 00
1234. &]
[s0; &]
[s3;H4;:Section`_1`_3: 1.3 StringBuffer&]
@ -473,7 +474,7 @@ concrete types.&]
[s7; &]
[s7; DUMP(date);&]
[s0; &]
[s17; date `= 12/16/2017&]
[s17; date `= 01/08/2018&]
[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 `= 2017&]
[s17; (int)date.month `= 12&]
[s17; (int)date.day `= 16&]
[s17; (int)date.year `= 2018&]
[s17; (int)date.month `= 1&]
[s17; (int)date.day `= 8&]
[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 `= 12/17/2017&]
[s17; `-`-date `= 12/15/2017&]
[s17; `+`+date `= 12/16/2017&]
[s17; date `+ 1 `= 01/09/2018&]
[s17; `-`-date `= 01/07/2018&]
[s17; `+`+date `= 01/08/2018&]
[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) `= 6559&]
[s17; date `- Date(2000, 1, 1) `= 6582&]
[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) `= 6&]
[s17; DayOfWeek(date) `= 1&]
[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) `= 12/31/2017&]
[s17; FirstDayOfMonth(date) `= 12/01/2017&]
[s17; LastDayOfYear(date) `= 12/31/2017&]
[s17; FirstDayOfYear(date) `= 01/01/2017&]
[s17; DayOfYear(date) `= 350&]
[s17; LastDayOfMonth(date) `= 01/31/2018&]
[s17; FirstDayOfMonth(date) `= 01/01/2018&]
[s17; LastDayOfYear(date) `= 12/31/2018&]
[s17; FirstDayOfYear(date) `= 01/01/2018&]
[s17; DayOfYear(date) `= 8&]
[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) `= 08/16/2019&]
[s17; AddMonths(date, 20) `= 09/08/2019&]
[s17; GetMonths(date, date `+ 100) `= 3&]
[s17; GetMonthsP(date, date `+ 100) `= 4&]
[s17; AddYears(date, 2) `= 12/16/2019&]
[s17; AddYears(date, 2) `= 01/08/2020&]
[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 `= 12/16/2017 14:21:41&]
[s17; (Date)time `= 12/16/2017&]
[s17; (int)time.hour `= 14&]
[s17; (int)time.minute `= 21&]
[s17; (int)time.second `= 41&]
[s17; time `= 01/08/2018 10:46:53&]
[s17; (Date)time `= 01/08/2018&]
[s17; (int)time.hour `= 10&]
[s17; (int)time.minute `= 46&]
[s17; (int)time.second `= 53&]
[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 `= 12/16/2017 14:21:42&]
[s17; time `+ 24 `* 3600 `= 12/17/2017 14:21:41&]
[s17; time `+ 1 `= 01/08/2018 10:46:54&]
[s17; time `+ 24 `* 3600 `= 01/09/2018 10:46:53&]
[s17; time `- date `= 0&]
[s17; time `- ToTime(date) `= 51701&]
[s17; time `- ToTime(date) `= 38813&]
[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 12/16/2017 12/16/2017
14:21:41&]
[s17; sout `= 1.23 12/16/2017 12/16/2017 14:21:41&]
[s17; LoadFile(ConfigFile(`"test.txt`")) `= 1.23 01/08/2018 01/08/2018
10:46:53&]
[s17; sout `= 1.23 01/08/2018 01/08/2018 10:46:53&]
[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:&]
@ -1068,8 +1069,8 @@ in both little`-endian and big`-endian modes:&]
[s7; ss.Put32be(0x12345678);&]
[s7; DUMPHEX(ss.GetResult());&]
[s0; &]
[s17; ss.GetResult() `= Memory at 0x01FEF2D0, size 0x8 `= 8&]
[s17; `+0 0x01FEF2D0 78 56 34 12 12 34 56 78
[s17; ss.GetResult() `= Memory at 0x0218F8E4, size 0x8 `= 8&]
[s17; `+0 0x0218F8E4 78 56 34 12 12 34 56 78
xV4..4Vx &]
[s0; &]
[s0; &]
@ -1118,11 +1119,11 @@ 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 0x07B71DD0, size
[s17; String((const char `*)data, size) `= Memory at 0x07CE1DD0, size
0x14 `= 20&]
[s17; `+0 0x07B71DD0 54 68 69 73 20 69 73 20 61 20 74 65 73 74
[s17; `+0 0x07CE1DD0 54 68 69 73 20 69 73 20 61 20 74 65 73 74
20 31 This is a test 1&]
[s17; `+16 0x07B71DE0 32 33 34 35
[s17; `+16 0x07CE1DE0 32 33 34 35
2345 &]
[s0; &]
[s5; [*C@5 TeeStream] sends output data to two separate streams:&]
@ -1146,11 +1147,11 @@ block to stream data:&]
[s7; while(!ms.IsEof())&]
[s7; -|DUMPHEX(ms.GetLine());&]
[s0; &]
[s17; ms.GetLine() `= Memory at 0x01FEF154, size 0x9 `= 9&]
[s17; `+0 0x01FEF154 53 6F 6D 65 20 6C 69 6E 65
[s17; ms.GetLine() `= Memory at 0x0218F768, size 0x9 `= 9&]
[s17; `+0 0x0218F768 53 6F 6D 65 20 6C 69 6E 65
Some line &]
[s17; ms.GetLine() `= Memory at 0x01FEF154, size 0xC `= 12&]
[s17; `+0 0x01FEF154 41 6E 6F 74 68 65 72 20 6C 69 6E 65
[s17; ms.GetLine() `= Memory at 0x0218F768, size 0xC `= 12&]
[s17; `+0 0x0218F768 41 6E 6F 74 68 65 72 20 6C 69 6E 65
Another line &]
[s0; &]
[s3;H4;:Section`_2`_3: 2.3 Binary serialization&]
@ -1395,7 +1396,7 @@ value.&]
[s7; &]
[s7; DUMP(v);&]
[s0; &]
[s17; v `= `[987, 1030, 989, 997, 1012, 948, 1020, 1029, 989, 999`]&]
[s17; v `= `[987, 1039, 1032, 958, 1008, 986, 960, 1083, 988, 959`]&]
[s0; &]
[s5; You can apply algorithms on containers, e.g. Sort&]
[s0; &]
@ -1403,7 +1404,7 @@ value.&]
[s7; &]
[s7; DUMP(v);&]
[s0; &]
[s17; v `= `[948, 987, 989, 989, 997, 999, 1012, 1020, 1029, 1030`]&]
[s17; v `= `[958, 959, 960, 986, 987, 988, 1008, 1032, 1039, 1083`]&]
[s0; &]
[s3;H4;:Section`_3`_3: 3.3 Transfer issues&]
[s5; Often you need to pass content of one container to another of
@ -1509,15 +1510,15 @@ to it:&]
[s7; DUMPC(dist);&]
[s0; &]
[s17; dist:&]
[s17; -|`[0`] `= Test 5: `[1954, 1988, 2018, 1994, 2046`]&]
[s17; -|`[1`] `= Test 6: `[1666, 1671, 1624, 1654, 1721, 1664`]&]
[s17; -|`[2`] `= Test 7: `[1420, 1480, 1472, 1393, 1401, 1412, 1422`]&]
[s17; -|`[3`] `= Test 8: `[1303, 1235, 1252, 1196, 1197, 1285, 1254,
1278`]&]
[s17; -|`[4`] `= Test 9: `[1139, 1062, 1164, 1133, 1048, 1125, 1117,
1128, 1084`]&]
[s17; -|`[5`] `= Test 10: `[973, 983, 1024, 981, 1000, 1037, 979, 1032,
995, 996`]&]
[s17; -|`[0`] `= Test 5: `[1998, 1997, 2042, 2021, 1942`]&]
[s17; -|`[1`] `= Test 6: `[1648, 1606, 1676, 1732, 1692, 1646`]&]
[s17; -|`[2`] `= Test 7: `[1476, 1360, 1446, 1415, 1452, 1426, 1425`]&]
[s17; -|`[3`] `= Test 8: `[1208, 1272, 1251, 1245, 1248, 1202, 1300,
1274`]&]
[s17; -|`[4`] `= Test 9: `[1130, 1098, 1101, 1042, 1104, 1149, 1111,
1154, 1111`]&]
[s17; -|`[5`] `= Test 10: `[956, 992, 1005, 1008, 1056, 979, 964, 1054,
948, 1038`]&]
[s0; &]
[s5; Another possibility is to use [*C@5 Vector`::Add(T`&`&)] method,
which uses pick`-constructor instead of deep`-copy constructor.
@ -2682,11 +2683,11 @@ is for the most part seamless:&]
[s0; &]
[s17; a `= 1&]
[s17; b `= 2.34&]
[s17; c `= 12/16/2017&]
[s17; c `= 01/08/2018&]
[s17; d `= hello&]
[s17; x `= 1&]
[s17; y `= 2.34&]
[s17; z `= 12/16/2017&]
[s17; z `= 01/08/2018&]
[s17; s `= hello&]
[s0; &]
[s5; As for primitive types, Value seamlessly works with [*C@5 int],
@ -2718,7 +2719,7 @@ as it is supported by these types):&]
[s0; &]
[s17; i `= 1&]
[s17; j `= 2&]
[s17; k `= 12/16/2017 00:00:00&]
[s17; k `= 01/08/2018 00:00:00&]
[s17; t `= hello&]
[s0; &]
[s5; To determine type of value stored in [*C@5 Value], you can use
@ -3347,14 +3348,14 @@ thread to [*C@5 Wait] for its completion:&]
[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 thread 2&]
[s17; In the thread 3&]
[s17; In the main thread 2&]
[s17; In the main thread 3&]
[s17; In the thread 3&]
[s17; In the thread 4&]
[s17; In the main thread 4&]
[s17; About to wait for thread to finish&]
[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&]
@ -3402,7 +3403,7 @@ code demonstrates why:&]
[s7; t.Wait();&]
[s7; DUMP(sum);&]
[s0; &]
[s17; sum `= 1031155&]
[s17; sum `= 1087631&]
[s0; &]
[s5; While the expected value is 2000000, produced value is different.
The problem is that both thread read / modify / write [*C@5 sum]
@ -3527,13 +3528,13 @@ testing data&]
[s7; DUMP(w);&]
[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, esse, cillum, eu, fugiat, nulla, pariatur, Excepteur,
Duis, aute, irure, in, reprehenderit, voluptate, velit, officia,
deserunt, mollit, anim, id, est, laborum, ullamco, laboris, nisi,
aliquip, ex, ea, commodo, consequat, sint, occaecat, cupidatat,
non, proident, sunt, culpa, qui`]&]
elit, sed, do, eiusmod, tempor, incididunt, ut, labore, et, dolore,
magna, Duis, aute, irure, in, reprehenderit, voluptate, velit,
officia, deserunt, mollit, anim, id, est, laborum, sint, occaecat,
cupidatat, non, proident, sunt, culpa, qui, aliqua, Ut, enim,
ad, minim, veniam, quis, nostrud, exercitation, esse, cillum,
eu, fugiat, nulla, pariatur, Excepteur, ullamco, laboris, nisi,
aliquip, ex, ea, commodo, consequat`]&]
[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
@ -3561,13 +3562,13 @@ end of CoWork job&]
[s7; DUMP(w);&]
[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, esse, cillum, eu, fugiat, nulla, pariatur, Excepteur,
Duis, aute, irure, in, reprehenderit, voluptate, velit, officia,
deserunt, mollit, anim, id, est, laborum, ullamco, laboris, nisi,
aliquip, ex, ea, commodo, consequat, sint, occaecat, cupidatat,
non, proident, sunt, culpa, qui`]&]
elit, sed, do, eiusmod, tempor, incididunt, ut, labore, et, dolore,
magna, Duis, aute, irure, in, reprehenderit, voluptate, velit,
officia, deserunt, mollit, anim, id, est, laborum, sint, occaecat,
cupidatat, non, proident, sunt, culpa, qui, aliqua, Ut, enim,
ad, minim, veniam, quis, nostrud, exercitation, esse, cillum,
eu, fugiat, nulla, pariatur, Excepteur, ullamco, laboris, nisi,
aliquip, ex, ea, commodo, consequat`]&]
[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]
@ -3758,7 +3759,38 @@ h) `{&]
[s0; &]
[s17; sum `= 49995000&]
[s0; &]
[s3;H4;:Section`_7`_7: 7.7 Parallel algorithms&]
[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,
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.&]
[s0; &]
[s7; Vector<String> data;&]
[s7; for(int i `= 0; i < 100; i`+`+)&]
[s7; -|data.Add(AsString(1.0 / i));&]
[s7; &]
[s7; double sum `= 0;&]
[s7; &]
[s7; CoWork co;&]
[s7; co `* `[`&`] `{&]
[s7; -|int i;&]
[s7; -|double m `= 0;&]
[s7; -|while((i `= co.Next()) < data.GetCount())&]
[s7; -|-|m `+`= atof(data`[i`]);&]
[s7; -|CoWork`::FinLock();&]
[s7; -|sum `+`= m;&]
[s7; `};&]
[s7; &]
[s7; DUMP(sum);&]
[s0; &]
[s17; sum `= 1e299&]
[s0; &]
[s3;H4;:Section`_7`_8: 7.8 Parallel algorithms&]
[s5; U`+`+ provides a parallel versions of algorithms where it makes
sense. The naming scheme is `'Co`' prefix before the name of
algorithm designates the parallel version.&]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After