Skip to content

Instantly share code, notes, and snippets.

@bigs
Created August 20, 2015 22:39
Show Gist options
  • Save bigs/5e7c1fcf5d41b747de78 to your computer and use it in GitHub Desktop.
Save bigs/5e7c1fcf5d41b747de78 to your computer and use it in GitHub Desktop.
#pragma once
#include <chrono>
#include <concord/time_utils.hpp>
namespace bolt {
class SnowflakeWorker {
public:
SnowflakeWorker(const uint8_t datacenterId, const uint8_t workerId)
: datacenterId_(datacenterId), workerId_(workerId) {}
virtual ~SnowflakeWorker() {}
uint64_t nextId() {
sequence_ = (sequence_ + 1) & sequenceMask;
uint64_t time = timeNowMilli();
// when the sequence wraps back to 0 (at 4096), we have to guarantee that
// the last key is greater than this key
if(sequence_ == 0) {
while(time <= lastTimestamp_) {
time = timeNowMilli();
}
}
lastTimestamp_ = time;
return (lastTimestamp_ << (sequenceBits + workerBits + datacenterBits))
| ((datacenterId_ & 0b11111) << (sequenceBits + workerBits))
| ((workerBits & 0b11111) << sequenceBits) | sequence_;
}
private:
const uint8_t sequenceBits = 12;
const uint8_t workerBits = 5;
const uint8_t datacenterBits = 5;
const uint8_t timestampBits = 64 - datacenterBits - workerBits - sequenceBits;
const uint64_t sequenceMask = -1 ^ (-1 << sequenceBits);
uint16_t sequence_{0};
uint64_t lastTimestamp_{0};
uint8_t datacenterId_;
uint8_t workerId_;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment