Skip to content

Instantly share code, notes, and snippets.

@buchgr
Created January 13, 2016 21:54
Show Gist options
  • Save buchgr/aaef825e5db9668a789e to your computer and use it in GitHub Desktop.
Save buchgr/aaef825e5db9668a789e to your computer and use it in GitHub Desktop.
#ifndef PARALLEL_ZEROER_HPP
#define PARALLEL_ZEROER_HPP
#include <atomic>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
class ParallelZeroer {
private:
boost::asio::io_service service;
boost::asio::io_service::work work;
boost::thread_group threads;
public:
static ParallelZeroer& instance(size_t parallelism) {
static ParallelZeroer pz(parallelism);
return pz;
}
void zeroMemory(void *p, size_t size) {
// invariant: nthreads is one less than a power of two.
size_t nthreads = this->threads.size();
size_t divisible_size = size & ~nthreads;
size_t remainder = size & nthreads;
size_t chunk_size = divisible_size / (nthreads + 1);
std::atomic<unsigned> counter(nthreads);
for (size_t i = 0; i < nthreads; i++) {
this->service.post(boost::bind(doZeroMem, ((uint8_t*)p) + i * chunk_size, chunk_size, std::ref(counter)));
}
memset(((uint8_t*)p) + divisible_size - chunk_size, 0, chunk_size + remainder);
while (counter.load()) {
asm volatile("pause");
}
}
private:
ParallelZeroer(size_t parallelism) : work(service) {
checkPowerOfTwo(parallelism);
for (size_t i = 0; i < parallelism - 1; i++) {
this->threads.create_thread(boost::bind(&boost::asio::io_service::run, &(this->service)));
}
}
static void doZeroMem(void *p, size_t size, std::atomic<unsigned> &counter) {
memset(p, 0, size);
counter--;
}
static void checkPowerOfTwo(size_t val) {
if (val > 0 && (val & val-1) != 0) {
throw std::runtime_error("val must be a power of two");
}
}
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment