Skip to content

Instantly share code, notes, and snippets.

@leifwalsh
Created April 6, 2014 19:37
Show Gist options
  • Save leifwalsh/10010580 to your computer and use it in GitHub Desktop.
Save leifwalsh/10010580 to your computer and use it in GitHub Desktop.
#include <atomic>
class spin_lock {
std::atomic<bool> _lock;
public:
spin_lock(const spin_lock&) = delete;
spin_lock& operator=(const spin_lock&) = delete;
spin_lock() : _lock(false) {}
class scoped_lock {
spin_lock &_lock;
public:
scoped_lock(const scoped_lock&) = delete;
scoped_lock& operator=(const scoped_lock&) = delete;
scoped_lock(spin_lock &lock) : _lock(lock) {
bool expect = false;
while (!_lock._lock.compare_exchange_weak(expect, true)) {
expect = false;
}
}
~scoped_lock() {
_lock._lock = false;
}
};
};
template<class mutex, class lock_object>
void spinner(mutex *m, int *val, std::size_t n) {
for (std::size_t i = 0; i < n; ++i) {
lock_object lk(*m);
(*val)++;
}
}
#include <chrono>
template<typename Clock>
class timer {
std::chrono::time_point<Clock> _t0;
public:
timer() : _t0(Clock::now()) {}
timer(const timer&) = delete;
timer& operator=(const timer&) = delete;
void reset() { _t0 = Clock::now(); }
operator std::chrono::milliseconds() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - _t0);
}
};
#include <algorithm>
#include <functional>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
template<class mutex, class lock_object>
void test(const std::string &name, std::size_t nthreads) {
std::vector<std::thread> threads;
mutex m;
int i = 0;
timer<std::chrono::high_resolution_clock> t;
std::generate_n(std::back_inserter(threads), nthreads,
[&m, &i, nthreads]() { return std::move(std::thread(&spinner<mutex, lock_object>, &m, &i, (1<<24) / nthreads)); });
std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
std::cout << name << " " << nthreads << ":\t" << static_cast<std::chrono::milliseconds>(t).count() << "ms" << std::endl;
}
int main(void) {
for (std::size_t i = 1; i <= std::thread::hardware_concurrency(); ++i) {
test<spin_lock, spin_lock::scoped_lock>("spinlock", i);
}
for (std::size_t i = 1; i <= std::thread::hardware_concurrency(); ++i) {
test<std::mutex, std::unique_lock<std::mutex> >("std::mutex", i);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment