Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating and reusing unique ID in C++ [closed]

Tags:

c++

I am working on a requirement where requests should have unique number from -2 to -101 inclusive, i.e., there are unique 100 requests at a time. If there are more than 100 requests at a given time then I should send error. Initially I have no requests. Once I sent requests I will take unique number say -2 , -3 and so on. Here requirement is that I may get command from client don't sent request to server for example -2 so I should delete this request and I should reuse this number for future request.

What is the best way to implement this in C++?

Also, I am not supposed to use Boost.

like image 922
venkysmarty Avatar asked Oct 24 '25 05:10

venkysmarty


2 Answers

Expanding on my std::bitset comment:

You can use the id as the index of the bitset and the value (true/false) as the availability of the id.

class IdStorage {
    const int N = 100;
   std::bitset<N> ids;

   bool allIdsUsed() { 
       return ids.all();
   }

   int getId() {
     if(allIdsUsed())
         throw "Error";

     for(int i = 0; i < N; ++i )
        if(ids.test(i))
            return i - 2;
   }

   void releaseId(int i) {
       ids.set(i + 2);
    }

}

Note that typed this in class, out of my head. Check the documentation

like image 141
TeaOverflow Avatar answered Oct 26 '25 17:10

TeaOverflow


You have to maintain a collection of unused ids at least. Additionally I would throw in a lookup table to verify that an id was handed out (for robustness). For both, I would suggest to use an std::vector, not a list.

First, store the unused collection in an std::vector<int>, which you can very easily initialise:

class IdStore {
  private:
    std::vector<int> unused;
    static int const MIN_ID = -101;
    static int const MAX_ID = -2;
  public:
    IdStore::IdStore()
    : unused(MAX_ID - MIN_ID + 1) {
      for (auto i = 0; i <= MAX_ID-MIN_ID; ++i) {
        unused[i] = i;
      }
    }
    int getId();
    void releaseId(int);
};

Additionally, you may want to keep track of the used ids, so you can verify if they were handed out; I'd use an std::vector<bool> used; member for that, which you can initialise simply with used(MAX_ID - MIN_ID +1) as its values will all default to false initially. Of course, you can make used also a bitset but note that this would require the distance from MIN_ID to MAX_ID to be known at compile time.

Handing out stuff is pretty simple from there:

int IdStore::getId() {
  if (unused.empty())
    throw "error"; // put something better here
  auto r = unused.back();
  used[r] = true;
  unused.pop_back();
  return MIN_ID + r;
}

And releasing them, also:

void IdStore::releaseId(int id) {
  if (id < MIN_ID || id > MAX_ID)
    throw "error"; // put something better here
  id -= MIN_ID;
  if (!used[id])
    throw "error"; // put something better here
  used[id] = false;
  unused.push_back(id);
}

Note that no reallocations take place! The vector will keep its size and neither getId nor releaseId will require expensive calls to malloc or free contrary to an approach using a list.

like image 26
bitmask Avatar answered Oct 26 '25 18:10

bitmask