Do we have thread lock?

Do we have a thread lock to make sure our code is thread-safe?

It’s generally not something to worry about when using VEXcode. Was there a particular situation you were concerned about ?

4 Likes

I wanna build a thread pool, which allows me to limit the total number of threads and avoid always creating and deleting threads. I’ve solved the problem of how to give the functions args, but I need a thread lock to make sure that one task can only be picked up to run once.

ThreadPool.h

#ifndef THREAD_POOL_H
#define THREAD_POOL_H

#include "vex.h"
#include "Head.h"
#include "Parameters.h"
#include <cstdlib>
#include <vector>

namespace ThreadPool {
  using namespace std;
  
  extern vector<ThreadInfo> *THREAD_INFO;
  
  class Pool {
    private:
      thread **threads = NULL;
      static int run(void);
      unsigned char num;
    public:
      vector<TaskInfo> *tasks = new vector<TaskInfo>(TASK_NUM);
      bool threadLock = false;
      bool end = false;
      Pool(const unsigned char &num);
      ~Pool();
      void AddTask(void (*func)(void), int32_t *id, bool *finish);
      void StopTask(const int32_t &id);
  };

  typedef struct ThreadInfo {
    Pool *pool;
    vector<int32_t> *idList;
  } ThreadInfo;

  typedef struct TaskInfo {
    void (*func)(void);
    int32_t *id;
    bool *finish;
  } TaskInfo;
}

#endif

ThreadPool.cpp

#include "ThreadPool.h"

namespace ThreadPool {
  vector<ThreadInfo> *THREAD_INFO = new vector<ThreadInfo>(THREAD_POOL_NUM);

  Pool::Pool(const unsigned char &num) {
    this->num = num;
    vector<int32_t> *list = new vector<int32_t>(num);
    this->threads = (thread **)malloc(num * sizeof(thread *));
    thread *temp = NULL;
    for (unsigned char i = 0; i < num; i++) {
      temp = new thread(this->run);
      list->push_back(temp->get_id());
      this->threads[i] = temp;
    }
    THREAD_INFO->push_back((ThreadInfo){this, list});
  }

  Pool::~Pool() {
    free(this->threads);
    delete this->tasks;
    vector<ThreadInfo>::iterator temp;
    for (temp = THREAD_INFO->begin(); temp < THREAD_INFO->end(); temp++) {
      if ((*temp).pool == this) {
        delete (*temp).idList;
        THREAD_INFO->erase(temp);
        break;
      }
    }
  }

  void Pool::AddTask(void (*func)(void), int32_t *id, bool *finish) {
    *finish = false;
    this->tasks->push_back((TaskInfo){func, id, finish});
  }

  void Pool::StopTask(const int32_t &id) {
    for (unsigned char i = 0; i < this->num; i++) {
      if (this->threads[i]->get_id() == id) {
        this->threads[i]->interrupt();
        delete this->threads[i];
        this->threads[i] = new thread(this->run);
        break;
      }
    }
  }

  int Pool::run(void) {
    int32_t id = this_thread::get_id();
    vector<ThreadInfo>::iterator temp1;
    vector<int32_t>::iterator temp2;
    for (temp1 = THREAD_INFO->begin(); temp1 < THREAD_INFO->end(); temp1++) {
      for (temp2 = temp1->idList->begin(); temp2 < temp1->idList->end(); temp2++) {
        if (*temp2 == id) {
          break;
        }
      }
    }
    Pool *pool = temp1->pool;
    vector<TaskInfo> *tasks = pool->tasks;
    while (true) {
      if (pool->end) {
        break;
      }
      while (pool->threadLock) {
        this_thread::sleep_for(THREAD_LOCK);
      }
      pool->threadLock = true;
      if (!tasks->empty()) {
        TaskInfo Task = tasks->at(0);
        tasks->erase(tasks->begin());
        pool->threadLock = false;
        void (*func)(void) = Task.func;
        *Task.id = id;
        func();
        *Task.finish = true;
      } else {
        pool->threadLock = false;
      }
      this_thread::sleep_for(THREAD_TIME);
    }
    return 0;
  }
}

And a function to init thread pool

void initThreadPool(void) {
    THREAD_POOL = new ThreadPool::Pool(THREAD_NUM);
  }

In the function “run”, there is a thread lock but it doesn’t work well because it can only lower the possibility of having an error.

Does this even build and run ? Seems a bit over complicated. A vex::thread is quite different from a std::thread. If it builds, send me a working example and I will take a look next week.

4 Likes

No. No way to make sure it’s thread safe. Always memory error.