13cb1fd8eSs.makeev_local // The MIT License (MIT) 23cb1fd8eSs.makeev_local // 33cb1fd8eSs.makeev_local // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 43cb1fd8eSs.makeev_local // 53cb1fd8eSs.makeev_local // Permission is hereby granted, free of charge, to any person obtaining a copy 63cb1fd8eSs.makeev_local // of this software and associated documentation files (the "Software"), to deal 73cb1fd8eSs.makeev_local // in the Software without restriction, including without limitation the rights 83cb1fd8eSs.makeev_local // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 93cb1fd8eSs.makeev_local // copies of the Software, and to permit persons to whom the Software is 103cb1fd8eSs.makeev_local // furnished to do so, subject to the following conditions: 113cb1fd8eSs.makeev_local // 123cb1fd8eSs.makeev_local // The above copyright notice and this permission notice shall be included in 133cb1fd8eSs.makeev_local // all copies or substantial portions of the Software. 143cb1fd8eSs.makeev_local // 153cb1fd8eSs.makeev_local // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163cb1fd8eSs.makeev_local // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173cb1fd8eSs.makeev_local // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 183cb1fd8eSs.makeev_local // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 193cb1fd8eSs.makeev_local // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 203cb1fd8eSs.makeev_local // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 213cb1fd8eSs.makeev_local // THE SOFTWARE. 223cb1fd8eSs.makeev_local 233cb1fd8eSs.makeev_local #pragma once 243cb1fd8eSs.makeev_local 253cb1fd8eSs.makeev_local 263cb1fd8eSs.makeev_local namespace MT 273cb1fd8eSs.makeev_local { 283cb1fd8eSs.makeev_local 293cb1fd8eSs.makeev_local // Hybrid spin wait 303cb1fd8eSs.makeev_local // 313cb1fd8eSs.makeev_local // http://www.1024cores.net/home/lock-free-algorithms/tricks/spinning 323cb1fd8eSs.makeev_local // 333cb1fd8eSs.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 343cb1fd8eSs.makeev_local class SpinWait 353cb1fd8eSs.makeev_local { 363cb1fd8eSs.makeev_local int32 iteration; 373cb1fd8eSs.makeev_local 383cb1fd8eSs.makeev_local public: 393cb1fd8eSs.makeev_local 403cb1fd8eSs.makeev_local static const int32 YIELD_CPU_THRESHOLD = 10; 413cb1fd8eSs.makeev_local static const int32 YIELD_CPU_THRESHOLD2 = 20; 423cb1fd8eSs.makeev_local static const int32 YIELD_THREAD_THRESHOLD = 40; 433cb1fd8eSs.makeev_local static const int32 YIELD_SLEEP0_THRESHOLD = 200; 443cb1fd8eSs.makeev_local 453cb1fd8eSs.makeev_local SpinWait()463cb1fd8eSs.makeev_local SpinWait() 473cb1fd8eSs.makeev_local : iteration(0) 483cb1fd8eSs.makeev_local { 493cb1fd8eSs.makeev_local } 503cb1fd8eSs.makeev_local Reset()513cb1fd8eSs.makeev_local void Reset() 523cb1fd8eSs.makeev_local { 533cb1fd8eSs.makeev_local iteration = 0; 543cb1fd8eSs.makeev_local } 553cb1fd8eSs.makeev_local IsActive()563cb1fd8eSs.makeev_local bool IsActive() const 573cb1fd8eSs.makeev_local { 583cb1fd8eSs.makeev_local return (iteration != 0); 593cb1fd8eSs.makeev_local } 603cb1fd8eSs.makeev_local SpinOnce()613cb1fd8eSs.makeev_local int32 SpinOnce() 623cb1fd8eSs.makeev_local { 633cb1fd8eSs.makeev_local if (iteration <= YIELD_CPU_THRESHOLD) 643cb1fd8eSs.makeev_local { 65*b086e50bSSergey Makeev MT::YieldProcessor(); 663cb1fd8eSs.makeev_local } else 673cb1fd8eSs.makeev_local { 683cb1fd8eSs.makeev_local if (iteration <= YIELD_CPU_THRESHOLD2) 693cb1fd8eSs.makeev_local { 703cb1fd8eSs.makeev_local for (int32 i = 0; i < 50; i++) 713cb1fd8eSs.makeev_local { 72*b086e50bSSergey Makeev MT::YieldProcessor(); 733cb1fd8eSs.makeev_local } 743cb1fd8eSs.makeev_local } else 753cb1fd8eSs.makeev_local { 763cb1fd8eSs.makeev_local if (iteration <= YIELD_THREAD_THRESHOLD) 773cb1fd8eSs.makeev_local { 783cb1fd8eSs.makeev_local MT::YieldThread(); 793cb1fd8eSs.makeev_local } else 803cb1fd8eSs.makeev_local { 813cb1fd8eSs.makeev_local if (iteration <= YIELD_SLEEP0_THRESHOLD) 823cb1fd8eSs.makeev_local { 833cb1fd8eSs.makeev_local MT::Thread::Sleep(0); 843cb1fd8eSs.makeev_local } else 853cb1fd8eSs.makeev_local { 863cb1fd8eSs.makeev_local MT::Thread::Sleep(1); 873cb1fd8eSs.makeev_local } 883cb1fd8eSs.makeev_local } 893cb1fd8eSs.makeev_local } 903cb1fd8eSs.makeev_local } 913cb1fd8eSs.makeev_local 923cb1fd8eSs.makeev_local int32 retValue = iteration; 933cb1fd8eSs.makeev_local if (iteration < INT_MAX) 943cb1fd8eSs.makeev_local { 953cb1fd8eSs.makeev_local iteration++; 963cb1fd8eSs.makeev_local } 973cb1fd8eSs.makeev_local return retValue; 983cb1fd8eSs.makeev_local } 993cb1fd8eSs.makeev_local }; 1003cb1fd8eSs.makeev_local 1013cb1fd8eSs.makeev_local 1023cb1fd8eSs.makeev_local /* 1033cb1fd8eSs.makeev_local 1043cb1fd8eSs.makeev_local Brute force spin wait. For testing purposes only! 1053cb1fd8eSs.makeev_local 1063cb1fd8eSs.makeev_local */ SpinSleepMicroSeconds(uint32 microseconds)1073cb1fd8eSs.makeev_local inline void SpinSleepMicroSeconds(uint32 microseconds) 1083cb1fd8eSs.makeev_local { 1093cb1fd8eSs.makeev_local int64 desiredTime = GetTimeMicroSeconds() + microseconds; 1103cb1fd8eSs.makeev_local for(;;) 1113cb1fd8eSs.makeev_local { 1123cb1fd8eSs.makeev_local int64 timeNow = GetTimeMicroSeconds(); 1133cb1fd8eSs.makeev_local if (timeNow > desiredTime) 1143cb1fd8eSs.makeev_local { 1153cb1fd8eSs.makeev_local break; 1163cb1fd8eSs.makeev_local } 117*b086e50bSSergey Makeev YieldProcessor(); 1183cb1fd8eSs.makeev_local } 1193cb1fd8eSs.makeev_local } 1203cb1fd8eSs.makeev_local 1213cb1fd8eSs.makeev_local /* 1223cb1fd8eSs.makeev_local 1233cb1fd8eSs.makeev_local Brute force spin wait. For testing purposes only! 1243cb1fd8eSs.makeev_local 1253cb1fd8eSs.makeev_local */ SpinSleepMilliSeconds(uint32 milliseconds)1263cb1fd8eSs.makeev_local inline void SpinSleepMilliSeconds(uint32 milliseconds) 1273cb1fd8eSs.makeev_local { 1283cb1fd8eSs.makeev_local SpinSleepMicroSeconds(milliseconds * 1000); 1293cb1fd8eSs.makeev_local } 1303cb1fd8eSs.makeev_local 1313cb1fd8eSs.makeev_local } 132