liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
src/robust.cpp
@@ -16,49 +16,59 @@
 * =====================================================================================
 */
#include "robust.h"
#include <chrono>
#include <thread>
using namespace std::chrono;
using namespace std::chrono_literals;
namespace
{
void yield() { std::this_thread::sleep_for(10us); }
} // namespace
namespace robust
{
namespace
bool AtomicReqRep::ClientRequest(const Data request, Data &reply)
{
static_assert(sizeof(steady_clock::duration) == sizeof(int64_t));
auto Now() { return steady_clock::now().time_since_epoch(); }
void Yield() { std::this_thread::sleep_for(10us); }
} // namespace
void QuickSleep() { Yield(); }
bool FMutex::try_lock()
{
   if (flock(fd_, LOCK_EX | LOCK_NB) == 0) {
      ++count_;
      if (mtx_.try_lock()) {
         return true;
      } else {
         if (--count_ == 0) {
            flock(fd_, LOCK_UN);
         }
   auto end_time = now() + 3s;
   do {
      Data cur = data_.load();
      if (GetState(cur) == eStateFree &&
          DataCas(cur, Encode(request, eStateRequest))) {
         do {
            yield();
            cur = data_.load();
            if (GetState(cur) == eStateReply) {
               DataCas(cur, Encode(0, eStateFree));
               reply = Decode(cur);
               return true;
            }
         } while (now() < end_time);
      }
      yield();
   } while (now() < end_time);
   return false;
}
bool AtomicReqRep::ServerProcess(Handler onReq)
{
   Data cur = data_.load();
   switch (GetState(cur)) {
   case eStateRequest:
      if (DataCas(cur, Encode(onReq(Decode(cur)), eStateReply))) {
         timestamp_ = now();
         return true;
      }
      break;
   case eStateReply:
      if (timestamp_.load() + 3s < now()) {
         DataCas(cur, Encode(0, eStateFree));
      }
      break;
   case eStateFree:
   default: break;
   }
   return false;
}
void FMutex::lock()
{
   flock(fd_, LOCK_EX);
   ++count_;
   mtx_.lock();
}
void FMutex::unlock()
{
   mtx_.unlock();
   if (--count_ == 0) {
      flock(fd_, LOCK_UN);
   }
}
} // namespace robust