feat(utils): ✨ threads: implement threadpool
This commit is contained in:
parent
5293b26854
commit
c16a52e27e
1
.cocorc
1
.cocorc
@ -8,3 +8,4 @@ scopes:
|
|||||||
- "logger"
|
- "logger"
|
||||||
- "macros"
|
- "macros"
|
||||||
- "sched"
|
- "sched"
|
||||||
|
- "utils"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
22
.github/img/logo-utils-threads.svg
vendored
Normal file
22
.github/img/logo-utils-threads.svg
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 191.24081">
|
||||||
|
<style>
|
||||||
|
.a { fill: #000000; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.a { fill: #ffffff; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<path class="a" d="M4.91962,1.516H0V0H20.42877V61.6416h4.6695v1.51648H.3335V61.6416H4.91962ZM32.68567,58.60962q-5.33725-5.3865-5.33649-15.45264,0-10.06072,5.71161-15.49371,5.71014-5.432,16.051-5.432,10.33767,0,15.42578,5.01056Q69.62248,32.25306,69.624,42.5265,69.624,63.999,48.44489,64,38.02069,64,32.68567,58.60962ZM43.35858,39.83124v6.56811q0,9.18109.54187,11.03144a18.93828,18.93828,0,0,0,1.12549,3.032,3.54887,3.54887,0,0,0,3.58575,2.02167q3.252,0,4.25214-3.79071.751-2.69324.75079-12.12592v-7.1575a57.79352,57.79352,0,0,0-.87579-11.916q-.87543-3.74541-4.04382-3.74713a4.161,4.161,0,0,0-2.96,1.05242,6.48727,6.48727,0,0,0-1.62616,3.495A64.70016,64.70016,0,0,0,43.35858,39.83124ZM137.33051,61.6416V0H116.90173V1.516h4.91962V61.6416h-4.58618v1.51648H142V61.6416Zm-59.36792-3.032q-5.33793-5.3865-5.33741-15.4526,0-10.06071,5.7116-15.49371,5.71161-5.432,16.051-5.432,10.33839,0,15.42669,5.01056,5.08347,5.01123,5.08538,15.28473Q114.89988,63.999,93.721,64q-10.423,0-15.75841-5.39038ZM88.6355,39.83124v6.56811q0,9.18109.541,11.03144a18.93282,18.93282,0,0,0,1.12641,3.032,3.54716,3.54716,0,0,0,3.58477,2.02167q3.25276,0,4.25269-3.79071.75165-2.69324.75122-12.12592h.00006v-7.1575a57.81812,57.81812,0,0,0-.87634-11.916q-.87533-3.74541-4.04425-3.74713a4.16006,4.16006,0,0,0-2.95954,1.05242,6.48473,6.48473,0,0,0-1.62567,3.495A64.70861,64.70861,0,0,0,88.6355,39.83124Z" />
|
||||||
|
<path class="a" d="M0,80.25H142V78H0Z" />
|
||||||
|
<path class="a" d="M0,152.24486H142v-2.25H0Z" />
|
||||||
|
<path class="a" d="M92.049,109.16356l-1.09813-2.66236a.991.991,0,0,0-1.67594-.25792l-1.856,2.21418L86.147,105.37439a.97233.97233,0,0,0-.7659-.6013.986.986,0,0,0-.91.3435l-1.856,2.21417-1.27182-3.08307a.96633.96633,0,0,0-.766-.60141.98631.98631,0,0,0-.91.34349l-1.90857,2.27748L77.52,105.7577a.99161.99161,0,0,0-.67174-.54538l-6.71756-1.5756-1.10854-1.10854H80.66009c3.55837,0,8.51612-2.49945,9.24715-5.83851a1.35158,1.35158,0,0,0-1.34649-1.59775h-30.394l.001.001A8.26067,8.26067,0,0,0,52.099,108.98056l.00121,5.35885-1.87395,1.72992a.98906.98906,0,0,0-.234,1.12912l1.20924,2.73389a.99154.99154,0,0,0,.90654.5904l.98569-.00037.98376-.00024a.99135.99135,0,0,0,.90605-.591l1.20754-2.73474a.98883.98883,0,0,0-.23468-1.12887l-1.87323-1.72871-.00108-3.33L70.486,127.41265h-6.559a.99151.99151,0,0,0-.90242,1.404l.77267,1.69059H57.60224V128.8999a1.49012,1.49012,0,0,0-1.48725-1.48725h-.46283a5.78278,5.78278,0,0,0-5.77665,5.77666,1.96616,1.96616,0,0,0,1.96363,1.96364h30.063l-.0374-.02a8.26253,8.26253,0,0,0,5.64655-14.1157L72.79163,106.29762l3.13632.73564.69424,1.48362a.9915.9915,0,0,0,.67174.54538.8496.8496,0,0,0,.09743.01694.98175.98175,0,0,0,.88886-.34652l1.856-2.21417,1.27194,3.08307a.97436.97436,0,0,0,.76589.60141.98632.98632,0,0,0,.91-.34349l1.85592-2.21417L86.212,110.7284a.97012.97012,0,0,0,.766.60129.986.986,0,0,0,.91-.34349L89.744,108.772l.47288,1.14727a.991.991,0,1,0,1.83219-.75573Zm-4.413-12.08864c-1.13093,1.8771-4.53788,3.47026-6.976,3.47026H67.03918l-3.028-3.028c-.16848-.16848-.36262-.29133-.54138-.44226ZM54.09181,117.04413,53.43,118.53925l-.337.00012-.33889.00012-.66277-1.49475,1.00058-.92361Zm-2.2333,16.14518a3.79783,3.79783,0,0,1,3.76073-3.79365v2.10306a.99093.99093,0,0,0,.9915.9915H65.3406a.99151.99151,0,0,0,.90242-1.404l-.77267-1.69058H72.469l3.332,3.332c.16968.16969.365.2935.54513.44528ZM86.109,131.32552a6.30442,6.30442,0,0,1-8.90584-.00012L53.70293,107.8253a6.29746,6.29746,0,0,1,8.906-8.906l23.50022,23.50022A6.30457,6.30457,0,0,1,86.109,131.32552Z" />
|
||||||
|
<path class="a" d="M76.12644,128.56186l1.37094,1.37094a1.59615,1.59615,0,0,0,2.25727,0l.5933-.5933.5933.5933a1.59613,1.59613,0,0,0,2.25726,0l1.37094-1.37094a1.59635,1.59635,0,0,0,0-2.25726l-.5933-.59331.59318-.59318a1.59628,1.59628,0,0,0,0-2.25738l-1.37094-1.37082a1.596,1.596,0,0,0-2.25726,0l-.59318.59318-.5933-.5933a1.59615,1.59615,0,0,0-2.25727,0l-1.37094,1.37094a1.59613,1.59613,0,0,0,0,2.25726l.59331.5933-.59331.59331A1.59613,1.59613,0,0,0,76.12644,128.56186Zm1.99547-4.25273-.31977-.31977.82387-.82387.31977.31977a1.9829,1.9829,0,0,0,2.80433,0l.31965-.31965.82387.82387-.31965.31965a1.98291,1.98291,0,0,0,0,2.80433l.31965.31977-.82375.82387-.31977-.31977a1.98279,1.98279,0,0,0-2.80433,0l-.31977.31977-.82387-.82387.31977-.31977A1.98279,1.98279,0,0,0,78.12191,124.30913Z" />
|
||||||
|
<path class="a" d="M54.57812,99.94146a5.07517,5.07517,0,1,0,7.17737,0A5.0752,5.0752,0,0,0,54.57812,99.94146Zm5.7752,5.77521a3.09221,3.09221,0,1,1,0-4.37292A3.09567,3.09567,0,0,1,60.35332,105.71667Z" />
|
||||||
|
<path class="a" d="M18.36865,190.8326a5.27325,5.27325,0,0,1-4.0459-1.42382,5.11787,5.11787,0,0,1-1.32617-3.62989V177.233H8.23682v-3.94433h3.09375a2.32246,2.32246,0,0,0,1.59814-.44238,2.19173,2.19173,0,0,0,.47608-1.63184v-4.11426h4.624v6.18848h6.834V177.233h-6.834v9.65528h6.834v3.94433Z" />
|
||||||
|
<path class="a" d="M26.69824,165.67245h5.03223V176.485h.20361a7.45052,7.45052,0,0,1,.748-1.39453,5.112,5.112,0,0,1,1.07129-1.13868,5.02969,5.02969,0,0,1,1.46191-.78222,5.74287,5.74287,0,0,1,1.88672-.28906,6.13036,6.13036,0,0,1,2.312.4248,4.72907,4.72907,0,0,1,1.80176,1.27539,6.15648,6.15648,0,0,1,1.17383,2.07422,8.59148,8.59148,0,0,1,.4248,2.82129V190.8326H37.78223V180.15682q0-3.3999-2.958-3.40039a4.2873,4.2873,0,0,0-1.13916.15332,3.03881,3.03881,0,0,0-1.00293.47559,2.261,2.261,0,0,0-.95166,1.9209V190.8326H26.69824Z" />
|
||||||
|
<path class="a" d="M44.68359,186.88827h4.0459V177.233h-4.0459v-3.94433h9.07813v4.96387H54A9.96642,9.96642,0,0,1,54.66309,176.4a6.03151,6.03151,0,0,1,1.08789-1.59864,4.82164,4.82164,0,0,1,1.61523-1.10449,5.65281,5.65281,0,0,1,2.24414-.4082h1.666v4.624H57.53613a3.52966,3.52966,0,0,0-2.82226,1.10059,3.97513,3.97513,0,0,0-.95215,2.69336v5.18164H59.542v3.94433H44.68359Z" />
|
||||||
|
<path class="a" d="M71.20312,191.24081q-4.41942,0-6.69824-2.44825a9.39649,9.39649,0,0,1-2.27734-6.66406,11.74991,11.74991,0,0,1,.59473-3.85937,8.28212,8.28212,0,0,1,1.70019-2.92383,7.20513,7.20513,0,0,1,2.68555-1.83594,9.55214,9.55214,0,0,1,3.55371-.6289,9.41435,9.41435,0,0,1,3.53564.6289,7.36548,7.36548,0,0,1,2.65235,1.78516,8.00214,8.00214,0,0,1,1.68359,2.80469,10.84171,10.84171,0,0,1,.59473,3.68945v1.49609H67.22559v.30567a3.66558,3.66558,0,0,0,1.05371,2.7373,4.23494,4.23494,0,0,0,3.09375,1.03711,5.65477,5.65477,0,0,0,2.687-.5957,6.34133,6.34133,0,0,0,1.9375-1.58008l2.7207,2.958a8.50391,8.50391,0,0,1-2.85644,2.17578A10.40186,10.40186,0,0,1,71.20312,191.24081Zm-.4082-14.75586a3.44782,3.44782,0,0,0-2.60058,1.00293,3.72753,3.72753,0,0,0-.96875,2.70312v.27149h7.07177V180.191a3.797,3.797,0,0,0-.93457-2.7207A3.36916,3.36916,0,0,0,70.79492,176.485Z" />
|
||||||
|
<path class="a" d="M95.4458,190.8326a3.78683,3.78683,0,0,1-2.51562-.79882,3.35073,3.35073,0,0,1-1.12207-2.29493h-.16993a4.30718,4.30718,0,0,1-1.88672,2.61817,6.38163,6.38163,0,0,1-3.45117.88379,5.93034,5.93034,0,0,1-4.09668-1.377,4.895,4.895,0,0,1-1.54785-3.85937,4.5489,4.5489,0,0,1,2.00684-4.08008,10.7109,10.7109,0,0,1,5.88183-1.32617h2.82129v-.88379a3.39415,3.39415,0,0,0-.73047-2.36328,3.22044,3.22044,0,0,0-2.46484-.79883,4.84266,4.84266,0,0,0-2.584.6123,5.97584,5.97584,0,0,0-1.7002,1.59766L81.13232,176.315a6.597,6.597,0,0,1,2.77051-2.46582,10.5984,10.5984,0,0,1,4.84571-.96875,8.67047,8.67047,0,0,1,5.62695,1.64941,6.05082,6.05082,0,0,1,2.02246,4.98047v7.68457h1.93848v3.63769ZM88.20459,187.943a3.79713,3.79713,0,0,0,2.24316-.64649,2.14388,2.14388,0,0,0,.918-1.87012v-2.10742H88.68018q-3.09375,0-3.09375,2.07324v.68067a1.56815,1.56815,0,0,0,.71386,1.39355A3.37411,3.37411,0,0,0,88.20459,187.943Z" />
|
||||||
|
<path class="a" d="M111.28955,187.60506h-.23828a6.81872,6.81872,0,0,1-1.88672,2.624,5.00879,5.00879,0,0,1-3.31543,1.01172,6.427,6.427,0,0,1-2.66894-.544,5.41158,5.41158,0,0,1-2.07422-1.666,8.35932,8.35932,0,0,1-1.35938-2.85645,17.4044,17.4044,0,0,1,0-8.22754,8.35917,8.35917,0,0,1,1.35938-2.85644,5.42062,5.42062,0,0,1,2.07422-1.666,6.4272,6.4272,0,0,1,2.66894-.54394,5.87045,5.87045,0,0,1,1.87012.27441,4.87285,4.87285,0,0,1,2.5332,1.90332,8.56033,8.56033,0,0,1,.79883,1.458h.23828V165.67245h5.03125V190.8326h-5.03125Zm-3.26465-.30859a4.05774,4.05774,0,0,0,2.29492-.6416,2.25465,2.25465,0,0,0,.96973-2.02637v-5.13574a2.25465,2.25465,0,0,0-.96973-2.02637,4.05774,4.05774,0,0,0-2.29492-.6416,3.32086,3.32086,0,0,0-2.61719,1.03027,4.14125,4.14125,0,0,0-.91894,2.8545v2.70215a4.13787,4.13787,0,0,0,.91894,2.85449A3.31759,3.31759,0,0,0,108.0249,187.29647Z" />
|
||||||
|
<path class="a" d="M125.603,191.24081a13.37005,13.37005,0,0,1-5.083-.88379A7.20142,7.20142,0,0,1,117.273,187.943l2.82226-2.61817a7.30324,7.30324,0,0,0,2.39649,1.751,7.48469,7.48469,0,0,0,3.14551.6289,4.98513,4.98513,0,0,0,2.3457-.459,1.50352,1.50352,0,0,0,.84961-1.41113,1.05824,1.05824,0,0,0-.57715-1.03711,5.84058,5.84058,0,0,0-1.59863-.459l-2.82227-.4414a11.67313,11.67313,0,0,1-2.21-.52735,5.79105,5.79105,0,0,1-1.76758-.96875,4.51755,4.51755,0,0,1-1.19043-1.49609,4.76243,4.76243,0,0,1-.4414-2.14258,5.07767,5.07767,0,0,1,2.10742-4.31738,9.76626,9.76626,0,0,1,5.916-1.56445,12.33259,12.33259,0,0,1,4.40332.69726,6.97606,6.97606,0,0,1,2.90722,1.98926l-2.5166,2.85547a6.39907,6.39907,0,0,0-2.00586-1.42774,6.87588,6.87588,0,0,0-2.958-.57812q-2.92383,0-2.92382,1.76758a1.08489,1.08489,0,0,0,.57812,1.07129,5.76485,5.76485,0,0,0,1.59766.459l2.78808.44238a11.72968,11.72968,0,0,1,2.21.52637,5.99763,5.99763,0,0,1,1.78516.96973,4.42248,4.42248,0,0,1,1.207,1.49609,4.74482,4.74482,0,0,1,.44238,2.1416,5.1541,5.1541,0,0,1-2.125,4.35156A9.87735,9.87735,0,0,1,125.603,191.24081Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 9.4 KiB |
13
.github/img/logo-utils.svg
vendored
Normal file
13
.github/img/logo-utils.svg
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 135.15295">
|
||||||
|
<style>
|
||||||
|
.a { fill: #000000; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.a { fill: #ffffff; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path class="a" d="M4.91962,1.516H0V0H20.42877V61.6416h4.6695v1.51648H.3335V61.6416H4.91962ZM32.68567,58.60962q-5.33725-5.3865-5.33649-15.45264,0-10.06072,5.71161-15.49371,5.71014-5.432,16.051-5.432,10.33767,0,15.42578,5.01056Q69.62248,32.25306,69.624,42.5265,69.624,63.999,48.44489,64,38.02069,64,32.68567,58.60962ZM43.35858,39.83124v6.56811q0,9.18109.54187,11.03144a18.93828,18.93828,0,0,0,1.12549,3.032,3.54887,3.54887,0,0,0,3.58575,2.02167q3.252,0,4.25214-3.79071.751-2.69324.75079-12.12592v-7.1575a57.79352,57.79352,0,0,0-.87579-11.916q-.87543-3.74541-4.04382-3.74713a4.161,4.161,0,0,0-2.96,1.05242,6.48727,6.48727,0,0,0-1.62616,3.495A64.70016,64.70016,0,0,0,43.35858,39.83124ZM137.33051,61.6416V0H116.90173V1.516h4.91962V61.6416h-4.58618v1.51648H142V61.6416Zm-59.36792-3.032q-5.33793-5.3865-5.33741-15.4526,0-10.06071,5.7116-15.49371,5.71161-5.432,16.051-5.432,10.33839,0,15.42669,5.01056,5.08347,5.01123,5.08538,15.28473Q114.89988,63.999,93.721,64q-10.423,0-15.75841-5.39038ZM88.6355,39.83124v6.56811q0,9.18109.541,11.03144a18.93282,18.93282,0,0,0,1.12641,3.032,3.54716,3.54716,0,0,0,3.58477,2.02167q3.25276,0,4.25269-3.79071.75165-2.69324.75122-12.12592h.00006v-7.1575a57.81812,57.81812,0,0,0-.87634-11.916q-.87533-3.74541-4.04425-3.74713a4.16006,4.16006,0,0,0-2.95954,1.05242,6.48473,6.48473,0,0,0-1.62567,3.495A64.70861,64.70861,0,0,0,88.6355,39.83124Z" />
|
||||||
|
<path class="a" d="M0,80.25H142V78H0Z" />
|
||||||
|
<path class="a" d="M92.049,109.16356l-1.09813-2.66236a.991.991,0,0,0-1.67594-.25792l-1.856,2.21418L86.147,105.37439a.97233.97233,0,0,0-.7659-.6013.986.986,0,0,0-.91.3435l-1.856,2.21417-1.27182-3.08307a.96633.96633,0,0,0-.766-.60141.98631.98631,0,0,0-.91.34349l-1.90857,2.27748L77.52,105.7577a.99161.99161,0,0,0-.67174-.54538l-6.71756-1.5756-1.10854-1.10854H80.66009c3.55837,0,8.51612-2.49945,9.24715-5.83851a1.35158,1.35158,0,0,0-1.34649-1.59775h-30.394l.001.001A8.26067,8.26067,0,0,0,52.099,108.98056l.00121,5.35885-1.87395,1.72992a.98906.98906,0,0,0-.234,1.12912l1.20924,2.73389a.99154.99154,0,0,0,.90654.5904l.98569-.00037.98376-.00024a.99135.99135,0,0,0,.90605-.591l1.20754-2.73474a.98883.98883,0,0,0-.23468-1.12887l-1.87323-1.72871-.00108-3.33L70.486,127.41265h-6.559a.99151.99151,0,0,0-.90242,1.404l.77267,1.69059H57.60224V128.8999a1.49012,1.49012,0,0,0-1.48725-1.48725h-.46283a5.78278,5.78278,0,0,0-5.77665,5.77666,1.96616,1.96616,0,0,0,1.96363,1.96364h30.063l-.0374-.02a8.26253,8.26253,0,0,0,5.64655-14.1157L72.79163,106.29762l3.13632.73564.69424,1.48362a.9915.9915,0,0,0,.67174.54538.8496.8496,0,0,0,.09743.01694.98175.98175,0,0,0,.88886-.34652l1.856-2.21417,1.27194,3.08307a.97436.97436,0,0,0,.76589.60141.98632.98632,0,0,0,.91-.34349l1.85592-2.21417L86.212,110.7284a.97012.97012,0,0,0,.766.60129.986.986,0,0,0,.91-.34349L89.744,108.772l.47288,1.14727a.991.991,0,1,0,1.83219-.75573Zm-4.413-12.08864c-1.13093,1.8771-4.53788,3.47026-6.976,3.47026H67.03918l-3.028-3.028c-.16848-.16848-.36262-.29133-.54138-.44226ZM54.09181,117.04413,53.43,118.53925l-.337.00012-.33889.00012-.66277-1.49475,1.00058-.92361Zm-2.2333,16.14518a3.79783,3.79783,0,0,1,3.76073-3.79365v2.10306a.99093.99093,0,0,0,.9915.9915H65.3406a.99151.99151,0,0,0,.90242-1.404l-.77267-1.69058H72.469l3.332,3.332c.16968.16969.365.2935.54513.44528ZM86.109,131.32552a6.30442,6.30442,0,0,1-8.90584-.00012L53.70293,107.8253a6.29746,6.29746,0,0,1,8.906-8.906l23.50022,23.50022A6.30457,6.30457,0,0,1,86.109,131.32552Z" />
|
||||||
|
<path class="a" d="M76.12644,128.56186l1.37094,1.37094a1.59615,1.59615,0,0,0,2.25727,0l.5933-.5933.5933.5933a1.59613,1.59613,0,0,0,2.25726,0l1.37094-1.37094a1.59635,1.59635,0,0,0,0-2.25726l-.5933-.59331.59318-.59318a1.59628,1.59628,0,0,0,0-2.25738l-1.37094-1.37082a1.596,1.596,0,0,0-2.25726,0l-.59318.59318-.5933-.5933a1.59615,1.59615,0,0,0-2.25727,0l-1.37094,1.37094a1.59613,1.59613,0,0,0,0,2.25726l.59331.5933-.59331.59331A1.59613,1.59613,0,0,0,76.12644,128.56186Zm1.99547-4.25273-.31977-.31977.82387-.82387.31977.31977a1.9829,1.9829,0,0,0,2.80433,0l.31965-.31965.82387.82387-.31965.31965a1.98291,1.98291,0,0,0,0,2.80433l.31965.31977-.82375.82387-.31977-.31977a1.98279,1.98279,0,0,0-2.80433,0l-.31977.31977-.82387-.82387.31977-.31977A1.98279,1.98279,0,0,0,78.12191,124.30913Z" />
|
||||||
|
<path class="a" d="M54.57812,99.94146a5.07517,5.07517,0,1,0,7.17737,0A5.0752,5.0752,0,0,0,54.57812,99.94146Zm5.7752,5.77521a3.09221,3.09221,0,1,1,0-4.37292A3.09567,3.09567,0,0,1,60.35332,105.71667Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
@ -29,9 +29,12 @@ path = "lib/lib.rs"
|
|||||||
"macros" = []
|
"macros" = []
|
||||||
# scheduling
|
# scheduling
|
||||||
"sched" = ["dep:chrono"]
|
"sched" = ["dep:chrono"]
|
||||||
"sched.tokio" = ["dep:tokio", "tokio?/time", "tokio?/rt"]
|
"sched.tokio" = ["dep:tokio", "tokio?/time", "tokio?/rt", "sched"]
|
||||||
"sched.rule-recurrence" = []
|
"sched.rule-recurrence" = ["sched"]
|
||||||
"sched.rule-cron" = []
|
"sched.rule-cron" = ["sched"]
|
||||||
|
# utils
|
||||||
|
"utils" = []
|
||||||
|
"utils.threads" = ["macros", "utils", "dep:log"]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src=".github/img/logo.svg" height="128"></p>
|
<p align="center"><img src=".github/img/logo.svg" width="200"></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@ -19,6 +19,16 @@ tasks:
|
|||||||
- cargo build --release
|
- cargo build --release
|
||||||
- python check_size.py
|
- python check_size.py
|
||||||
|
|
||||||
|
example:logger:
|
||||||
|
desc: 🚀 run lool «example logger»
|
||||||
|
cmds:
|
||||||
|
- cargo run --example=logger --release --features logger
|
||||||
|
|
||||||
|
example:threadpool:
|
||||||
|
desc: 🚀 run lool «example threadpool»
|
||||||
|
cmds:
|
||||||
|
- cargo run --example=threadpool --release --features utils.threads
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
desc: 🎨 format lool
|
desc: 🎨 format lool
|
||||||
cmds:
|
cmds:
|
||||||
|
|||||||
32
examples/threadpool.rs
Normal file
32
examples/threadpool.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use {
|
||||||
|
eyre::{Ok, Result},
|
||||||
|
lool::utils::threads::threadpool::ThreadPool,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn job(id: usize) {
|
||||||
|
// wait for a while
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
println!("job {}", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let pool = ThreadPool::create(4)?;
|
||||||
|
|
||||||
|
for i in 0..10 {
|
||||||
|
pool.execute(move || job(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all jobs to finish
|
||||||
|
// another way to do this is to call `pool.join()` but I want to log stuff in the meantime
|
||||||
|
loop {
|
||||||
|
println!("{:?}", pool);
|
||||||
|
if !pool.has_work() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for a while
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="./../../.github/img/logo-cli.svg" height="192"></p>
|
<p align="center"><img src="./../../.github/img/logo-cli.svg" width="200"></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
This crate is for internal use. It's only published privately.
|
This crate is for internal use. It's only published privately.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo add lool --registry=lugit --features cli
|
cargo add lool --registry=lugit --features cli {sub-feature}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Sub-Features
|
# Sub-Features
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="../../../.github/img/logo-cli-colors.svg" height="256"></p>
|
<p align="center"><img src="../../../.github/img/logo-cli-colors.svg" width="200"></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@ -9,3 +9,6 @@ pub mod logger;
|
|||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|
||||||
|
#[cfg(feature = "utils")]
|
||||||
|
pub mod utils;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="./../../.github/img/logo-logger.svg" height="192"></p>
|
<p align="center"><img src="./../../.github/img/logo-logger.svg" width="200"></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="./../../.github/img/logo-macros.svg" height="192"></p>
|
<p align="center"><img src="./../../.github/img/logo-macros.svg" width="200"></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="../../.github/img/logo-tokio-sched.svg" height="256"></p>
|
<p align="center"><img src="../../.github/img/logo-sched.svg" width="200"></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
This library is for internal use. And as such, it's only published privately.
|
This library is for internal use. And as such, it's only published privately.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo add lool --registry=lugit --features sched
|
cargo add lool --registry=lugit --features sched {sub-feature}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Sub-Features
|
# Sub-Features
|
||||||
@ -28,6 +28,10 @@ cargo add lool --registry=lugit --features sched
|
|||||||
|
|
||||||
Enables the `tokio` runtime support, replacing the default behaviour, which implies a `std::thread` pool to run the tasks.
|
Enables the `tokio` runtime support, replacing the default behaviour, which implies a `std::thread` pool to run the tasks.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> Not yet implemented
|
||||||
|
|
||||||
### <a href="#"><img alt="has subfeatures" src="../../.github/img/icon-has-submodules.svg" height="12"></a> sched.rule-recurrent
|
### <a href="#"><img alt="has subfeatures" src="../../.github/img/icon-has-submodules.svg" height="12"></a> sched.rule-recurrent
|
||||||
|
|
||||||
Enables the "**recurrent-rule**" style for scheduling tasks.
|
Enables the "**recurrent-rule**" style for scheduling tasks.
|
||||||
@ -44,13 +48,6 @@ Enables the "**recurrent-rule**" style for scheduling tasks.
|
|||||||
- `sched.rule-pyschedule`: Enables the [python schedule](https://pypi.org/project/schedule/)-like
|
- `sched.rule-pyschedule`: Enables the [python schedule](https://pypi.org/project/schedule/)-like
|
||||||
style for scheduling tasks
|
style for scheduling tasks
|
||||||
|
|
||||||
# Usage
|
|
||||||
|
|
||||||
<!--
|
|
||||||
TODO
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
# Inspiration
|
# Inspiration
|
||||||
|
|
||||||
This library is inspired by several other libraries, including:
|
This library is inspired by several other libraries, including:
|
||||||
@ -66,7 +63,7 @@ This library is inspired by several other libraries, including:
|
|||||||
a human-friendly API
|
a human-friendly API
|
||||||
|
|
||||||
|
|
||||||
Otros:
|
Other useful libraries that might come in handy for this project during development are:
|
||||||
|
|
||||||
- https://crates.io/crates/tokio-cron-scheduler
|
- https://crates.io/crates/tokio-cron-scheduler
|
||||||
- https://crates.io/crates/clokwerk
|
- https://crates.io/crates/clokwerk
|
||||||
|
|||||||
30
lib/utils/README.md
Normal file
30
lib/utils/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<p align="center"><img src="../../.github/img/logo-utils.svg" width="200"></p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<b>lool » <code>utils</code></b> contains utilities for some of the most common tasks and operations in the Rust programming language.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
This library is for internal use. And as such, it's only published privately.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo add lool --registry=lugit --features utils {sub-feature}?
|
||||||
|
```
|
||||||
|
|
||||||
|
# Sub-Features
|
||||||
|
|
||||||
|
This library is divided into several sub-features, each one providing a different set of utilities. This allows you to only include the parts you need, reducing compile times.
|
||||||
|
|
||||||
|
- [x] [`utils.threads`](./threads): utilities for working with threads in Rust.
|
||||||
|
|
||||||
|
<!-- TODO -->
|
||||||
2
lib/utils/mod.rs
Normal file
2
lib/utils/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(feature = "utils.threads")]
|
||||||
|
pub mod threads;
|
||||||
72
lib/utils/threads/README.md
Normal file
72
lib/utils/threads/README.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<p align="center"><img src="../../../.github/img/logo-utils-threads.svg" width="200"></p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<b>lool » <code>utils.threads</code></b> contains utilities for working with threads in Rust.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
This library is for internal use. And as such, it's only published privately.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo add lool --registry=lugit --features utils.threads
|
||||||
|
```
|
||||||
|
|
||||||
|
# Utilities
|
||||||
|
|
||||||
|
## Thread Pool
|
||||||
|
|
||||||
|
This is a super basic and lightweight thread pool implementation to use when there's not need for
|
||||||
|
a more complex solution.
|
||||||
|
|
||||||
|
This is basically, the `ThreadPool` implementation from the book ["The Rust Programming Language" (chapter 20)](https://doc.rust-lang.org/book/ch20-00-final-project-a-web-server.html)
|
||||||
|
by Steve Klabnik and Carol Nichols, but with some modifications and additions, inspired by the
|
||||||
|
[threadpool](https://crates.io/crates/threadpool) crate.
|
||||||
|
|
||||||
|
The `ThreadPool` implemented by the book waits for all threads to finish when the pool is dropped.
|
||||||
|
|
||||||
|
This behavior is ok for some cases, for example, for a web server that needs to wait for all
|
||||||
|
currently active requests to finish before shutting down. But it might not be the desired behavior
|
||||||
|
for other cases (e.g. long-running tasks when we can't wait for a thread to finish).
|
||||||
|
|
||||||
|
To keep this library generic enough, the `ThreadPool` implementation here exposes a `join` method
|
||||||
|
that explicitly waits for all threads to finish.
|
||||||
|
|
||||||
|
### More robust solutions
|
||||||
|
|
||||||
|
- [rayon](https://crates.io/crates/rayon): a data parallelism library for Rust.
|
||||||
|
- [threadpool](https://crates.io/crates/threadpool): a simple thread pool implementation (quite
|
||||||
|
abandoned).
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use lool::utils::threads::ThreadPool;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// create a thread pool with 4 threads
|
||||||
|
let pool = ThreadPool::new(4);
|
||||||
|
|
||||||
|
// spawn a bunch of tasks
|
||||||
|
for i in 0..8 {
|
||||||
|
pool.execute(move || {
|
||||||
|
println!("task {}", i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all tasks to finish
|
||||||
|
// unlike the book's implementation, this doesn't happen automatically when the pool is dropped
|
||||||
|
// e.g. when the program ends, so we need to join explicitly
|
||||||
|
pool.join();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, see the [`threadpool.rs`](../../../examples/threadpool.rs) example.
|
||||||
1
lib/utils/threads/mod.rs
Normal file
1
lib/utils/threads/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod threadpool;
|
||||||
201
lib/utils/threads/threadpool.rs
Normal file
201
lib/utils/threads/threadpool.rs
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
use {
|
||||||
|
crate::fail,
|
||||||
|
core::fmt,
|
||||||
|
eyre::Result,
|
||||||
|
std::{
|
||||||
|
fmt::{Debug, Formatter},
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
mpsc::{channel, Receiver, Sender},
|
||||||
|
Arc, Mutex,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
type Job = Box<dyn FnOnce() + Send + 'static>;
|
||||||
|
|
||||||
|
/// status of the thread pool
|
||||||
|
struct PoolStatus {
|
||||||
|
/// the number of pending jobs in the queue
|
||||||
|
queued_count: AtomicUsize,
|
||||||
|
/// the number of currently active jobs
|
||||||
|
active_count: AtomicUsize,
|
||||||
|
/// workers count
|
||||||
|
pool_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PoolStatus {
|
||||||
|
fn create(pool_size: usize) -> PoolStatus {
|
||||||
|
PoolStatus {
|
||||||
|
queued_count: AtomicUsize::new(0),
|
||||||
|
active_count: AtomicUsize::new(0),
|
||||||
|
pool_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns `true` if has active work (either queued or running)
|
||||||
|
fn has_work(&self) -> bool {
|
||||||
|
self.queued_count.load(Ordering::SeqCst) > 0 || self.active_count.load(Ordering::SeqCst) > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » a simple thread pool implementation
|
||||||
|
///
|
||||||
|
/// this is based on the example from the *"The Rust Programming Language"* book, with some
|
||||||
|
/// modifications inspired by the [threadpool](https://crates.io/crates/threadpool) crate.
|
||||||
|
///
|
||||||
|
/// unlike the original implementation from the book, this one doesn't wait for all jobs to finish
|
||||||
|
/// when the pool is dropped. Instead, it's up to the user to call `join` to wait for all jobs to
|
||||||
|
/// finish before dropping the pool. This allows the user to stop the pool and drop immediately if
|
||||||
|
/// that's what they want
|
||||||
|
///
|
||||||
|
/// **why?**
|
||||||
|
///
|
||||||
|
/// the implementation from the book was thought to be used in a web server where it's
|
||||||
|
/// important to wait till all active requests are finished before shutting down the server.
|
||||||
|
///
|
||||||
|
/// In other scenarios, though, this might not be necessary. For example, if we have a long-running
|
||||||
|
/// process and we need to shut down the pool, we might want to implement our own logic on how to
|
||||||
|
/// handle the shutdown. e.g. We might wait for some jobs, but not all of them, etc.
|
||||||
|
pub struct ThreadPool {
|
||||||
|
workers: Vec<Worker>,
|
||||||
|
job_sender: Option<Sender<Job>>,
|
||||||
|
status: Arc<PoolStatus>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ThreadPool {
|
||||||
|
/// 🧉 » creates a new `ThreadPool`.
|
||||||
|
///
|
||||||
|
/// The `capacity` is the number of threads in the pool.
|
||||||
|
///
|
||||||
|
/// **Errors**
|
||||||
|
///
|
||||||
|
/// If the `capacity` is zero, an error is returned.
|
||||||
|
pub fn create(capacity: usize) -> Result<ThreadPool> {
|
||||||
|
if capacity == 0 {
|
||||||
|
return fail!("ThreadPool size cannot be zero.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = Arc::new(PoolStatus::create(capacity));
|
||||||
|
|
||||||
|
let (job_sender, job_receiver) = channel();
|
||||||
|
let receiver = Arc::new(Mutex::new(job_receiver));
|
||||||
|
let mut workers = Vec::with_capacity(capacity);
|
||||||
|
|
||||||
|
for id in 0..capacity {
|
||||||
|
workers.push(Worker::new(id, receiver.clone(), status.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ThreadPool {
|
||||||
|
job_sender: Some(job_sender),
|
||||||
|
workers,
|
||||||
|
status,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » queues execution of a task/function in the thread pool
|
||||||
|
///
|
||||||
|
/// the function `f` will be executed as soon as a worker thread is free.
|
||||||
|
pub fn execute<F>(&self, f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce() + Send + 'static,
|
||||||
|
{
|
||||||
|
if let Some(ref job_sender) = self.job_sender {
|
||||||
|
self.status.queued_count.fetch_add(1, Ordering::SeqCst);
|
||||||
|
job_sender
|
||||||
|
.send(Box::new(f))
|
||||||
|
.expect("ThreadPool::execute unable to send job into queue.");
|
||||||
|
} else {
|
||||||
|
panic!("ThreadPool::execute called, but there's no job_sender... weird!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » returns the number of active jobs
|
||||||
|
pub fn active_jobs(&self) -> usize {
|
||||||
|
self.status.active_count.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » returns the number of queued jobs
|
||||||
|
pub fn queued_jobs(&self) -> usize {
|
||||||
|
self.status.queued_count.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » returns the pool size
|
||||||
|
pub fn pool_size(&self) -> usize {
|
||||||
|
self.status.pool_size
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » returns `true` if the pool has active work (either queued or running)
|
||||||
|
pub fn has_work(&self) -> bool {
|
||||||
|
self.status.has_work()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 🧉 » waits for all threads to finish their work
|
||||||
|
pub fn join(&mut self) {
|
||||||
|
drop(self.job_sender.take());
|
||||||
|
|
||||||
|
for worker in &mut self.workers {
|
||||||
|
println!("Shutting down worker {}", worker.id);
|
||||||
|
|
||||||
|
if let Some(thread) = worker.thread.take() {
|
||||||
|
thread.join().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ThreadPool {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("ThreadPool")
|
||||||
|
.field("queued_jobs", &self.queued_jobs())
|
||||||
|
.field("active_jobs", &self.active_jobs())
|
||||||
|
.field("pool_size", &self.pool_size())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the worker is responsible for executing the jobs on a specific thread.
|
||||||
|
///
|
||||||
|
/// it holds its own thread and waits for a job to be sent to it from the `ThreadPool::execute` fn.
|
||||||
|
/// Once it receives a job, it
|
||||||
|
/// executes
|
||||||
|
/// it and then waits for another job, until the `job_receiver` is dropped (usually when the pool
|
||||||
|
/// is dropped).
|
||||||
|
struct Worker {
|
||||||
|
id: usize,
|
||||||
|
thread: Option<thread::JoinHandle<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Worker {
|
||||||
|
fn new(
|
||||||
|
id: usize,
|
||||||
|
job_receiver: Arc<Mutex<Receiver<Job>>>,
|
||||||
|
pool_status: Arc<PoolStatus>,
|
||||||
|
) -> Worker {
|
||||||
|
let thread = thread::spawn(move || loop {
|
||||||
|
let message = {
|
||||||
|
// Only lock jobs for the time it takes to get a job, not to run it.
|
||||||
|
let lock = job_receiver.lock().expect("Worker thread unable to lock job_receiver");
|
||||||
|
lock.recv()
|
||||||
|
}; // drops the lock here and now others are free to get another job
|
||||||
|
|
||||||
|
let job = match message {
|
||||||
|
Ok(job) => job,
|
||||||
|
Err(..) => break,
|
||||||
|
};
|
||||||
|
|
||||||
|
pool_status.active_count.fetch_add(1, Ordering::SeqCst);
|
||||||
|
pool_status.queued_count.fetch_sub(1, Ordering::SeqCst);
|
||||||
|
|
||||||
|
job();
|
||||||
|
|
||||||
|
pool_status.active_count.fetch_sub(1, Ordering::SeqCst);
|
||||||
|
});
|
||||||
|
|
||||||
|
Worker {
|
||||||
|
id,
|
||||||
|
thread: Some(thread),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user