1 #ifndef SYNCOBJ__HPP 2 #define SYNCOBJ__HPP 3 4 /* $Id: SyncObj.hpp 573341 2018-10-25 17:53:05Z saprykin $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Authors: Dmitri Dmitrienko 30 * 31 * File Description: 32 * 33 * Synchronization classes and utilities 34 * 35 */ 36 37 #include <atomic> 38 #include <thread> 39 #include <signal.h> 40 #include <functional> 41 42 #include <corelib/ncbithr.hpp> 43 44 #include "IdCassScope.hpp" 45 46 47 BEGIN_IDBLOB_SCOPE 48 USING_NCBI_SCOPE; 49 50 bool WaitCondVar(unsigned int timeoutmks, CFastMutex & mtx, 51 CConditionVariable & ev, 52 const function<bool()> & is_done_cb, 53 const function<void(bool*)> & update_rslt_cb); 54 55 56 #ifdef __linux__ 57 class CFutex 58 { 59 public: 60 enum EWaitResult { 61 eWaitResultTimeOut, // value hasn't changed 62 eWaitResultOk, // value is changed and we waited 63 eWaitResultOkFast // value is changed but we didn't wait 64 }; 65 66 void DoWake(int waiters = INT_MAX); 67 68 public: CFutex(int start=0)69 CFutex(int start = 0) : 70 m_Value(start) 71 {} 72 73 CFutex& operator=(const CFutex&) = delete; 74 CFutex(const CFutex&) = delete; 75 CompareExchange(int expected,int replace_with,bool wake_others=true)76 bool CompareExchange(int expected, int replace_with, 77 bool wake_others = true) 78 { 79 bool rv = m_Value.compare_exchange_weak(expected, replace_with, 80 memory_order_relaxed); 81 if (rv && wake_others) 82 DoWake(); 83 return rv; 84 } 85 Value(void)86 int Value(void) 87 { 88 return m_Value; 89 } 90 91 EWaitResult WaitWhile(int value, int timeout_mks = -1); 92 Wake(void)93 void Wake(void) 94 { 95 DoWake(); 96 } 97 Set(int value,bool wake_others=true)98 int Set(int value, bool wake_others = true) 99 { 100 int rv = m_Value.exchange(value); 101 if ((rv != value) && wake_others) 102 DoWake(); 103 return rv; 104 } 105 Inc(bool wake_others=true)106 int Inc(bool wake_others = true) 107 { 108 int rv = atomic_fetch_add(&m_Value, 1); 109 if (wake_others) 110 DoWake(); 111 return rv; 112 } 113 Dec(bool wake_others=true)114 int Dec(bool wake_others = true) 115 { 116 int rv = atomic_fetch_sub(&m_Value, 1); 117 if (wake_others) 118 DoWake(); 119 return rv; 120 } 121 SemInc(void)122 int SemInc(void) 123 { 124 int rv = atomic_fetch_add(&m_Value, 1); 125 return rv; 126 } 127 SemDec(void)128 int SemDec(void) 129 { 130 int rv = atomic_fetch_sub(&m_Value, 1); 131 if (rv < 0) 132 DoWake(); 133 return rv; 134 } 135 136 private: 137 volatile atomic_int m_Value; 138 }; 139 #endif 140 141 142 class SSignalHandler 143 { 144 public: s_CtrlCPressed(void)145 static bool s_CtrlCPressed(void) 146 { 147 return sm_CtrlCPressed != 0; 148 } 149 150 static void s_WatchCtrlCPressed(bool enable, 151 function<void()> on_ctrl_c_pressed = NULL); 152 153 private: 154 static volatile sig_atomic_t sm_CtrlCPressed; 155 #ifdef __linux__ 156 static CFutex sm_CtrlCPressedEvent; 157 #endif 158 static unique_ptr<thread, function<void(thread*)> > sm_WatchThread; 159 static function<void()> sm_OnCtrlCPressed; 160 static volatile bool sm_Quit; 161 }; 162 163 164 END_IDBLOB_SCOPE 165 166 #endif 167