std::cv_status s4u::ConditionVariable::wait_for(std::unique_lock<Mutex>& lock, double timeout) {
  try {
    simcall_cond_wait_timeout(cond_, lock.mutex()->mutex_, timeout);
    return std::cv_status::timeout;
  }
  catch (xbt_ex& e) {

    // If the exception was a timeout, we have to take the lock again:
    if (e.category == timeout_error) {
      try {
        lock.mutex()->lock();
        return std::cv_status::timeout;
      }
      catch (...) {
        std::terminate();
      }
    }

    // Another exception: should we reaquire the lock?
    std::terminate();
  }
  catch (...) {
    std::terminate();
  }
}
Example #2
0
 virtual void erase (std::unique_lock <std::mutex>& guard, std::shared_ptr <Resource> resource) noexcept {
    assert (guard.mutex () == &m_mutex);
    
    resource_iterator ii = m_resources.find (resource->getId ());
    
    if (ii != resource_end ())
       m_resources.erase (ii);
 }
Example #3
0
void Solver::proceed(std::unique_lock<std::mutex>& lock)
{
	assert(lock.mutex() == &workerMutex && lock.owns_lock());
	wakeMainThreadRequested = true;
	wakeMainThread.notify_one();
	wakeWorkerThread.wait(lock, [&]() { return wakeWorkerThreadRequested; });
	wakeWorkerThreadRequested = false;
}
Example #4
0
void FunctionScheduler::addFunctionToHeap(
    const std::unique_lock<std::mutex>& lock,
    RepeatFunc&& func) {
  // This function should only be called with mutex_ already locked.
  DCHECK(lock.mutex() == &mutex_);
  DCHECK(lock.owns_lock());

  functions_.emplace_back(std::move(func));
  if (running_) {
    functions_.back().resetNextRunTime(steady_clock::now());
    std::push_heap(functions_.begin(), functions_.end(), fnCmp_);
    // Signal the running thread to wake up and see if it needs to change
    // its current scheduling decision.
    runningCondvar_.notify_one();
  }
}
Example #5
0
        void signal(std::unique_lock<mutex_type> l, std::int64_t count)
        {
            HPX_ASSERT_OWNS_LOCK(l);

            mutex_type* mtx = l.mutex();

            // release no more threads than we get resources
            value_ += count;
            for (std::int64_t i = 0; value_ >= 0 && i < count; ++i)
            {
                // notify_one() returns false if no more threads are
                // waiting
                if (!cond_.notify_one(std::move(l)))
                    break;

                l = std::unique_lock<mutex_type>(*mtx);
            }
        }
Example #6
0
void FunctionScheduler::cancelFunction(const std::unique_lock<std::mutex>& l,
                                       FunctionHeap::iterator it) {
  // This function should only be called with mutex_ already locked.
  DCHECK(l.mutex() == &mutex_);
  DCHECK(l.owns_lock());

  if (running_) {
    // Internally gcc has an __adjust_heap() function to fill in a hole in the
    // heap.  Unfortunately it isn't part of the standard API.
    //
    // For now we just leave the RepeatFunc in our heap, but mark it as unused.
    // When its nextTimeInterval comes up, the runner thread will pop it from
    // the heap and simply throw it away.
    it->cancel();
  } else {
    // We're not running, so functions_ doesn't need to be maintained in heap
    // order.
    functions_.erase(it);
  }
}
Example #7
0
   resource_iterator erase (std::unique_lock <std::mutex>& guard, resource_iterator ii) noexcept {
      assert (guard.mutex () == &m_mutex);

      return m_resources.erase (ii);
   }
Example #8
0
 virtual void insert (std::unique_lock <std::mutex>& guard, std::shared_ptr <Resource> resource) noexcept {
    assert (guard.mutex () == &m_mutex);
    m_resources.insert (std::make_pair (resource->getId (), resource));
 }
Example #9
0
void FunctionScheduler::runOneFunction(std::unique_lock<std::mutex>& lock,
                                       steady_clock::time_point now) {
  DCHECK(lock.mutex() == &mutex_);
  DCHECK(lock.owns_lock());

  // The function to run will be at the end of functions_ already.
  //
  // Fully remove it from functions_ now.
  // We need to release mutex_ while we invoke this function, and we need to
  // maintain the heap property on functions_ while mutex_ is unlocked.
  RepeatFunc func(std::move(functions_.back()));
  functions_.pop_back();
  if (!func.cb) {
    VLOG(5) << func.name << "function has been canceled while waiting";
    return;
  }
  currentFunction_ = &func;

  // Update the function's next run time.
  if (steady_) {
    // This allows scheduler to catch up
    func.setNextRunTimeSteady();
  } else {
    // Note that we set nextRunTime based on the current time where we started
    // the function call, rather than the time when the function finishes.
    // This ensures that we call the function once every time interval, as
    // opposed to waiting time interval seconds between calls.  (These can be
    // different if the function takes a significant amount of time to run.)
    func.setNextRunTimeStrict(now);
  }

  // Release the lock while we invoke the user's function
  lock.unlock();

  // Invoke the function
  try {
    VLOG(5) << "Now running " << func.name;
    func.cb();
  } catch (const std::exception& ex) {
    LOG(ERROR) << "Error running the scheduled function <"
      << func.name << ">: " << exceptionStr(ex);
  }

  // Re-acquire the lock
  lock.lock();

  if (!currentFunction_) {
    // The function was cancelled while we were running it.
    // We shouldn't reschedule it;
    return;
  }
  // Clear currentFunction_
  CHECK_EQ(currentFunction_, &func);
  currentFunction_ = nullptr;

  // Re-insert the function into our functions_ heap.
  // We only maintain the heap property while running_ is set.  (running_ may
  // have been cleared while we were invoking the user's function.)
  functions_.push_back(std::move(func));
  if (running_) {
    std::push_heap(functions_.begin(), functions_.end(), fnCmp_);
  }
}
/**
 * Wait functions
 */
void s4u::ConditionVariable::wait(std::unique_lock<Mutex>& lock) {
  simcall_cond_wait(cond_, lock.mutex()->mutex_);
}