| 51 | } |
| 52 | |
| 53 | void ThreadLock::ThreadOnce(ThreadOnceToken_t *onceToken, void (*callback)()) { |
| 54 | if (!onceToken || !callback) { |
| 55 | assert(onceToken); |
| 56 | assert(callback); |
| 57 | return; |
| 58 | } |
| 59 | while (true) { |
| 60 | auto expected = ThreadOnceUninitialized; |
| 61 | atomic_compare_exchange_weak(onceToken, &expected, ThreadOnceInitializing); |
| 62 | switch (expected) { |
| 63 | case ThreadOnceInitialized: |
| 64 | return; |
| 65 | case ThreadOnceUninitialized: |
| 66 | callback(); |
| 67 | onceToken->store(ThreadOnceInitialized); |
| 68 | return; |
| 69 | case ThreadOnceInitializing: { |
| 70 | // another thread is initializing, let's wait for 1ms |
| 71 | ThreadLock::Sleep(1); |
| 72 | break; |
| 73 | } |
| 74 | default: { |
| 75 | MMKVError("should never happen:%d", expected); |
| 76 | assert(0); |
| 77 | return; |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | void ThreadLock::Sleep(int ms) { |
| 84 | ::Sleep(ms); |
nothing calls this directly
no outgoing calls
no test coverage detected