AlexNet/include/pipedispenser.cuh
Laurent El Shafey 9fdd561586 Initial commit
2024-12-10 08:56:11 -08:00

139 lines
3.1 KiB
Text

/*
* pipedispenser.cuh
*
* Created on: 2013-03-01
* Author: spoon
*/
#ifndef PIPEDISPENSER_CUH_
#define PIPEDISPENSER_CUH_
#include <pthread.h>
#include <set>
#include <algorithm>
#include <iterator>
#include <util.cuh>
class PipeDispenser {
protected:
int _numPipes;
seti _pipes;
pthread_mutex_t *_mutex;
void lock() {
pthread_mutex_lock(_mutex);
}
void unlock() {
pthread_mutex_unlock(_mutex);
}
public:
PipeDispenser(const seti& pipes) {
_pipes.insert(pipes.begin(), pipes.end());
_mutex = (pthread_mutex_t*)(malloc(sizeof (pthread_mutex_t)));
pthread_mutex_init(_mutex, NULL);
}
virtual ~PipeDispenser() {
pthread_mutex_destroy(_mutex);
free(_mutex);
}
virtual int getPipe(const seti& interested) = 0;
int getPipe(int interested) {
seti tmp;
tmp.insert(interested);
return getPipe(tmp);
}
virtual void freePipe(int pipe) = 0;
};
/*
* This one blocks until there is a free pipe to return.
*/
class PipeDispenserBlocking : public PipeDispenser {
protected:
pthread_cond_t *_cv;
void wait() {
pthread_cond_wait(_cv, _mutex);
}
void broadcast() {
pthread_cond_broadcast(_cv);
}
int getAvailablePipes(const seti& interested, intv& available) {
available.clear();
std::set_intersection(_pipes.begin(), _pipes.end(), interested.begin(), interested.end(), std::back_inserter(available));
return available.size();
}
public:
PipeDispenserBlocking(const seti& pipes) : PipeDispenser(pipes) {
_cv = (pthread_cond_t*)(malloc(sizeof (pthread_cond_t)));
pthread_cond_init(_cv, NULL);
}
~PipeDispenserBlocking() {
pthread_cond_destroy(_cv);
free(_cv);
}
int getPipe(const seti& interested) {
lock();
intv avail;
while (getAvailablePipes(interested, avail) == 0) {
wait();
}
int pipe = avail[0];
_pipes.erase(pipe);
unlock();
return pipe;
}
void freePipe(int pipe) {
lock();
_pipes.insert(pipe);
broadcast();
unlock();
}
};
/*
* This one returns the least-occupied pipe.
*/
class PipeDispenserNonBlocking : public PipeDispenser {
protected:
std::map<int,int> _pipeUsers;
public:
PipeDispenserNonBlocking(const seti& pipes) : PipeDispenser(pipes) {
for (seti::iterator it = pipes.begin(); it != pipes.end(); ++it) {
_pipeUsers[*it] = 0;
}
}
int getPipe(const seti& interested) {
lock();
int pipe = -1, users = 1 << 30;
for (seti::iterator it = _pipes.begin(); it != _pipes.end(); ++it) {
if (interested.count(*it) > 0 && _pipeUsers[*it] < users) {
pipe = *it;
users = _pipeUsers[*it];
}
}
if (pipe >= 0) {
_pipeUsers[pipe]++;
}
unlock();
return pipe;
}
void freePipe(int pipe) {
lock();
_pipeUsers[pipe]--;
unlock();
}
};
#endif /* PIPEDISPENSER_CUH_ */