pros::rtos::RecursiveMutex class

Constructors, destructors, conversion operators

RecursiveMutex() constexpr
RecursiveMutex(const RecursiveMutex&) deleted
RecursiveMutex(RecursiveMutex&&) deleted
~RecursiveMutex()

Public functions

RecursiveMutex& operator=(const RecursiveMutex&) deleted
RecursiveMutex& operator=(RecursiveMutex&&) deleted
bool take()
Takes and locks a mutex indefinetly.
bool take(std::uint32_t timeout)
Takes and locks a mutex, waiting for up to a certain number of milliseconds before timing out.
bool give()
Unlocks a mutex.
void lock()
Takes and locks a mutex, waiting for up to TIMEOUT_MAX milliseconds.
void unlock()
Unlocks a mutex.
bool try_lock()
Try to lock a mutex.
template<typename Rep, typename Period>
bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)
Takes and locks a mutex, waiting for a specified duration.
template<typename Duration>
bool try_lock_until(const std::chrono::time_point<Clock, Duration>& abs_time)
Takes and locks a mutex, waiting until a specified time.

Function documentation

bool pros::rtos::RecursiveMutex::take()

Takes and locks a mutex indefinetly.

Returns True if the mutex was successfully taken, false otherwise. If false is returned, then errno is set with a hint about why the the mutex couldn't be taken

See https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes for details.

Example

// Global variables for the robot's odometry, which the rest of the robot's
// subsystems will utilize
double odom_x = 0.0;
double odom_y = 0.0;
double odom_heading = 0.0;

// This mutex protects the odometry data. Whenever we read or write to the
// odometry data, we should make copies into the local variables, and read
// all 3 values at once to avoid errors.
pros::RecursiveMutex odom_mutex;

void odom_task(void* param) {
  while(true) {
    // First we fetch the odom coordinates from the previous iteration of the
    // odometry task. These are put into local variables so that we can
    // keep the size of the critical section as small as possible. This lets
    // other tasks that need to use the odometry data run until we need to
    // update it again.
    odom_mutex.take();
    double x_old = odom_x;
    double y_old = odom_y;
    double heading_old = odom_heading;
    odom_mutex.give();

    double x_new = 0.0;
    double y_new = 0.0;
    double heading_new = 0.0;
    
    // --- Calculate new pose for the robot here ---

    // Now that we have the new pose, we can update the global variables
    odom_mutex.take();
    odom_x = x_new;
    odom_y = y_new;
    odom_heading = heading_new;
    odom_mutex.give();
    
    delay(10);
  }
}

void chassis_task(void* param) {
  while(true) {
    // Here we copy the current odom values into local variables so that
    // we can use them without worrying about the odometry task changing say,
    // the y value right after we've read the x. This ensures our values are
    // sound.
    odom_mutex.take();
    double current_x = odom_x;
    double current_y = odom_y;
    double current_heading = odom_heading;
    odom_mutex.give();
    
    // ---- Move the robot using the current locations goes here ----
    
    delay(10);
  }
}

void initialize() {
  odom_mutex = pros::RecursiveMutex();

  pros::Task odom_task(odom_task, "Odometry Task");
  pros::Task chassis_task(odom_task, "Chassis Control Task");
}

.

bool pros::rtos::RecursiveMutex::take(std::uint32_t timeout)

Takes and locks a mutex, waiting for up to a certain number of milliseconds before timing out.

Parameters
timeout Time to wait before the mutex becomes available. A timeout of 0 can be used to poll the mutex. TIMEOUT_MAX can be used to block indefinitely.
Returns True if the mutex was successfully taken, false otherwise. If false is returned, then errno is set with a hint about why the the mutex couldn't be taken.

See https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes for details.

Example

// Global variables for the robot's odometry, which the rest of the robot's
// subsystems will utilize
double odom_x = 0.0;
double odom_y = 0.0;
double odom_heading = 0.0;

// This mutex protects the odometry data. Whenever we read or write to the
// odometry data, we should make copies into the local variables, and read
// all 3 values at once to avoid errors.
pros::RecursiveMutex odom_mutex;

void odom_task(void* param) {
  while(true) {
    // First we fetch the odom coordinates from the previous iteration of the
    // odometry task. These are put into local variables so that we can
    // keep the size of the critical section as small as possible. This lets
    // other tasks that need to use the odometry data run until we need to
    // update it again.
    odom_mutex.take();
    double x_old = odom_x;
    double y_old = odom_y;
    double heading_old = odom_heading;
    odom_mutex.give();

    double x_new = 0.0;
    double y_new = 0.0;
    double heading_new = 0.0;
    
    // --- Calculate new pose for the robot here ---

    // Now that we have the new pose, we can update the global variables
    odom_mutex.take();
    odom_x = x_new;
    odom_y = y_new;
    odom_heading = heading_new;
    odom_mutex.give();
    
    delay(10);
  }
}

void chassis_task(void* param) {
  while(true) {
    // Here we copy the current odom values into local variables so that
    // we can use them without worrying about the odometry task changing say,
    // the y value right after we've read the x. This ensures our values are
    // sound.
    odom_mutex.take();
    double current_x = odom_x;
    double current_y = odom_y;
    double current_heading = odom_heading;
    odom_mutex.give();
    
    // ---- Move the robot using the current locations goes here ----
    
    delay(10);
  }
}

void initialize() {
  odom_mutex = pros::RecursiveMutex();

  pros::Task odom_task(odom_task, "Odometry Task");
  pros::Task chassis_task(odom_task, "Chassis Control Task");
}

.

bool pros::rtos::RecursiveMutex::give()

Unlocks a mutex.

Returns True if the mutex was successfully returned, false otherwise. If false is returned, then errno is set with a hint about why the mutex couldn't be returned.

See https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes for details.

Example

// Global variables for the robot's odometry, which the rest of the robot's
// subsystems will utilize
double odom_x = 0.0;
double odom_y = 0.0;
double odom_heading = 0.0;

// This mutex protects the odometry data. Whenever we read or write to the
// odometry data, we should make copies into the local variables, and read
// all 3 values at once to avoid errors.
pros::RecursiveMutex odom_mutex;

void odom_task(void* param) {
  while(true) {
    // First we fetch the odom coordinates from the previous iteration of the
    // odometry task. These are put into local variables so that we can
    // keep the size of the critical section as small as possible. This lets
    // other tasks that need to use the odometry data run until we need to
    // update it again.
    odom_mutex.take();
    double x_old = odom_x;
    double y_old = odom_y;
    double heading_old = odom_heading;
    odom_mutex.give();

    double x_new = 0.0;
    double y_new = 0.0;
    double heading_new = 0.0;
    
    // --- Calculate new pose for the robot here ---

    // Now that we have the new pose, we can update the global variables
    odom_mutex.take();
    odom_x = x_new;
    odom_y = y_new;
    odom_heading = heading_new;
    odom_mutex.give();
    
    delay(10);
  }
}

void chassis_task(void* param) {
  while(true) {
    // Here we copy the current odom values into local variables so that
    // we can use them without worrying about the odometry task changing say,
    // the y value right after we've read the x. This ensures our values are
    // sound.
    odom_mutex.take();
    double current_x = odom_x;
    double current_y = odom_y;
    double current_heading = odom_heading;
    odom_mutex.give();
    
    // ---- Move the robot using the current locations goes here ----
    
    delay(10);
  }
}

void initialize() {
  odom_mutex = pros::RecursiveMutex();

  pros::Task odom_task(odom_task, "Odometry Task");
  pros::Task chassis_task(odom_task, "Chassis Control Task");
}

.

void pros::rtos::RecursiveMutex::lock()

Takes and locks a mutex, waiting for up to TIMEOUT_MAX milliseconds.

Exceptions
std::system_error Mutex could not be locked within TIMEOUT_MAX milliseconds. see errno for details.

Effectively equivalent to calling pros::RecursiveMutex::take with TIMEOUT_MAX as the parameter.

Conforms to named requirment BasicLockable

Example

// Global variables for the robot's odometry, which the rest of the robot's
// subsystems will utilize
double odom_x = 0.0;
double odom_y = 0.0;
double odom_heading = 0.0;

// This mutex protects the odometry data. Whenever we read or write to the
// odometry data, we should make copies into the local variables, and read
// all 3 values at once to avoid errors.
pros::RecursiveMutex odom_mutex;

void odom_task(void* param) {
  while(true) {
    // First we fetch the odom coordinates from the previous iteration of the
    // odometry task. These are put into local variables so that we can
    // keep the size of the critical section as small as possible. This lets
    // other tasks that need to use the odometry data run until we need to
    // update it again.
    odom_mutex.lock();
    double x_old = odom_x;
    double y_old = odom_y;
    double heading_old = odom_heading;
    odom_mutex.unlock();

    double x_new = 0.0;
    double y_new = 0.0;
    double heading_new = 0.0;
    
    // --- Calculate new pose for the robot here ---

    // Now that we have the new pose, we can update the global variables
    odom_mutex.lock();
    odom_x = x_new;
    odom_y = y_new;
    odom_heading = heading_new;
    odom_mutex.unlock();
    
    delay(10);
  }
}

void chassis_task(void* param) {
  while(true) {
    // Here we copy the current odom values into local variables so that
    // we can use them without worrying about the odometry task changing say,
    // the y value right after we've read the x. This ensures our values are
    // sound.
    odom_mutex.lock();
    double current_x = odom_x;
    double current_y = odom_y;
    double current_heading = odom_heading;
    odom_mutex.unlock();
    
    // ---- Move the robot using the current locations goes here ----
    
    delay(10);
  }
}

void initialize() {
  odom_mutex = pros::RecursiveMutex();

  pros::Task odom_task(odom_task, "Odometry Task");
  pros::Task chassis_task(odom_task, "Chassis Control Task");
}

.

void pros::rtos::RecursiveMutex::unlock()

Unlocks a mutex.

Equivalent to calling pros::RecursiveMutex::give.

Conforms to named requirement BasicLockable

Example

// Global variables for the robot's odometry, which the rest of the robot's
// subsystems will utilize
double odom_x = 0.0;
double odom_y = 0.0;
double odom_heading = 0.0;

// This mutex protects the odometry data. Whenever we read or write to the
// odometry data, we should make copies into the local variables, and read
// all 3 values at once to avoid errors.
pros::RecursiveMutex odom_mutex;

void odom_task(void* param) {
  while(true) {
    // First we fetch the odom coordinates from the previous iteration of the
    // odometry task. These are put into local variables so that we can
    // keep the size of the critical section as small as possible. This lets
    // other tasks that need to use the odometry data run until we need to
    // update it again.
    odom_mutex.lock();
    double x_old = odom_x;
    double y_old = odom_y;
    double heading_old = odom_heading;
    odom_mutex.unlock();

    double x_new = 0.0;
    double y_new = 0.0;
    double heading_new = 0.0;
    
    // --- Calculate new pose for the robot here ---

    // Now that we have the new pose, we can update the global variables
    odom_mutex.lock();
    odom_x = x_new;
    odom_y = y_new;
    odom_heading = heading_new;
    odom_mutex.unlock();
    
    delay(10);
  }
}

void chassis_task(void* param) {
  while(true) {
    // Here we copy the current odom values into local variables so that
    // we can use them without worrying about the odometry task changing say,
    // the y value right after we've read the x. This ensures our values are
    // sound.
    odom_mutex.lock();
    double current_x = odom_x;
    double current_y = odom_y;
    double current_heading = odom_heading;
    odom_mutex.unlock();
    
    // ---- Move the robot using the current locations goes here ----
    
    delay(10);
  }
}

void initialize() {
  odom_mutex = pros::RecursiveMutex();

  pros::Task odom_task(odom_task, "Odometry Task");
  pros::Task chassis_task(odom_task, "Chassis Control Task");
}

.

bool pros::rtos::RecursiveMutex::try_lock()

Try to lock a mutex.

Returns True when lock was acquired succesfully, or false otherwise.

Returns immediately if unsucessful.

Conforms to named requirement Lockable

pros::RecursiveMutex mutex;

void my_task_fn(void* param) { while (true) { if(mutex.try_lock()) { printf("Mutex aquired successfully!\n"); // Do stuff that requires the protected resource here } else { printf("Mutex not aquired!\n"); } } }

template<typename Rep, typename Period>
bool pros::rtos::RecursiveMutex::try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)

Takes and locks a mutex, waiting for a specified duration.

Parameters
rel_time Time to wait before the mutex becomes available.
Returns True if the lock was acquired succesfully, otherwise false.

Equivalent to calling pros::RecursiveMutex::take with a duration specified in milliseconds.

Conforms to named requirement TimedLockable

Example

void my_task_fn(void* param) {
  while (true) {
    if(mutex.try_lock_for(std::chrono::milliseconds(100))) {
      printf("Mutex aquired successfully!\n");
      // Do stuff that requires the protected resource here
    }
    else {
      printf("Mutex not aquired after 100 milliseconds!\n");
    }
  }
}

template<typename Duration>
bool pros::rtos::RecursiveMutex::try_lock_until(const std::chrono::time_point<Clock, Duration>& abs_time)

Takes and locks a mutex, waiting until a specified time.

Parameters
abs_time Time point until which to wait for the mutex.
Returns True if the lock was acquired succesfully, otherwise false.

Conforms to named requirement TimedLockable

Example

void my_task_fn(void* param) {
  while (true) {
    // Get the current time point
    auto now = std::chrono::system_clock::now();

    // Calculate the time point 100 milliseconds from now
    auto abs_time = now + std::chrono::milliseconds(100);

    if(mutex.try_lock_until(abs_time)) {
      printf("Mutex aquired successfully!\n");
      // Do stuff that requires the protected resource here
    }
    else {
      printf("Mutex not aquired after 100 milliseconds!\n");
    }
  }
}