Page MenuHomec4science

grid.hh
No OneTemporary

File Metadata

Created
Mon, Oct 28, 20:45
#ifndef GRID_HH
#define GRID_HH
#include <QDebug>
#include <QMutex>
#include <QQueue>
#include <QMutexLocker>
#include <QSemaphore>
#include <cstddef>
#include <queue>
#include <vector>
enum GridState {
_normal_state,
_randomize,
_clear
};
class GridInfo {
public:
GridInfo() : _origin{0, 0}, _size{0, 0} {}
GridInfo(const int origin[2], const int size[2])
: _origin{origin[0], origin[1]}, _size{size[0], size[1]} {}
GridInfo(const GridInfo & other)
: _origin{other._origin[0], other._origin[1]},
_size{other._size[0], other._size[1]} {}
void setOrigin(const int origin[2]) {
_origin[0] = origin[0];
_origin[1] = origin[1];
}
void setSize(const int size[2]) {
_size[0] = size[0];
_size[1] = size[1];
}
int size(int i) const { return _size[i]; }
int origin(int i) const { return _origin[i]; }
const int * size() const { return _size; }
const int * origin() const { return _origin; }
protected:
int _origin[2];
int _size[2];
};
class SendGrid : public GridInfo {
typedef char T;
public:
SendGrid(const int origin[2], const int size[2])
: GridInfo(origin, size), _data(size[0] * size[1], 0){};
SendGrid(const SendGrid & other) : GridInfo(other), _data(other._data) {}
T & operator()(int i, int j) { return _data[i * _size[1] + j]; }
const T & operator()(int i, int j) const { return _data[i * _size[1] + j]; }
T * data() { return _data.data(); }
private:
std::vector<T> _data;
};
class Grid {
typedef uint32_t T;
public:
Grid(size_t m = 0, size_t n = 0)
: _pieces_sem(0), _nb_pieces(0), _data(n * m), _size{m, n}, _pieces(0),
_queues(0), _state(_normal_state) {
}
~Grid() { }
void resize(size_t m, size_t n) {
_size[0] = m;
_size[1] = n;
_data.resize(n * m);
}
T & operator()(size_t i, size_t j) { return _data[j + i * _size[1]]; }
const T & operator()(size_t i, size_t j) const {
return _data[j + i * _size[1]];
}
size_t getNbPieces() {
QMutexLocker locker(&_nb_pieces_lock);
return _nb_pieces;
}
size_t size(int i) const { return _size[i]; }
void getPiece() { return _pieces_sem.acquire(1); }
void setPiece(size_t nb_pieces) {
QMutexLocker locker(&_nb_pieces_lock);
_nb_pieces = nb_pieces;
_queues.clear();
_queues.resize(nb_pieces);
_pieces.resize(nb_pieces);
_state.resize(nb_pieces);
setState(_normal_state);
}
void releasePieces() { _pieces_sem.release(_nb_pieces); }
void releasePiece() { _pieces_sem.release(1); }
void unconnectPiece(__attribute__((unused)) int prank) {
QMutexLocker locker(&_nb_pieces_lock);
--_nb_pieces;
if (_nb_pieces == 0)
_pieces_sem.acquire(_pieces_sem.available());
}
void dataToSend(const SendGrid & grid) {
class Pred {
public:
Pred(const GridInfo & grid_info) : a(grid_info) {}
bool operator()(const GridInfo & b) {
return a.origin(0) >= b.origin(0) && a.origin(1) >= b.origin(1) &&
a.origin(0) < b.origin(0) + b.size(0) &&
a.origin(1) < b.origin(1) + b.size(1);
}
private:
const GridInfo & a;
};
Pred pred(grid);
auto it = std::find_if(_pieces.begin(), _pieces.end(), pred);
if (it == _pieces.end())
return;
qDebug() << "Click in piece" << (it - _pieces.begin());
bool split[2] = {false, false};
for (int i = 0; i < 2; ++i) {
if (it->origin(i) + it->size(i) < grid.origin(i) + grid.size(i))
split[i] = true;
}
qDebug() << "Need split" << split[0] << split[1];
auto extract_grid = [&grid, &pred, this](const int * origin,
const int * size) -> void {
qDebug() << "Extracting grid" << origin[0] << origin[1] << "--" << size[0]
<< size[1];
int offset[2] = {origin[0] - grid.origin(0), origin[1] - grid.origin(1)};
SendGrid sub_grid(origin, size);
for (int i = 0; i < size[0]; ++i)
for (int j = 0; j < size[1]; ++j)
sub_grid(i, j) = grid(i + offset[0], j + offset[1]);
Pred pred(sub_grid);
auto begin = _pieces.begin();
auto it = std::find_if(_pieces.begin(), _pieces.end(), pred);
if (it == _pieces.end())
return;
int q = it - begin;
qDebug() << "Queuing it for processor" << q;
_queues[q].enqueue(sub_grid);
};
int size[4];
for (int i = 0; i < 2; ++i) {
if (split[i]) {
size[i] = it->origin(i) + it->size(i) - grid.origin(i);
size[2 + i] = grid.size(i) - size[i];
} else {
size[i] = grid.size(i);
size[2 + i] = 0;
}
}
extract_grid(grid.origin(), size);
if (split[0]) {
int origin[2] = {grid.origin(0) + size[0], grid.origin(1)};
int ssize[2] = {size[2], size[1]};
extract_grid(origin, ssize);
}
if (split[1]) {
int origin[2] = {grid.origin(0), grid.origin(1) + size[1]};
int ssize[2] = {size[0], size[3]};
extract_grid(origin, ssize);
}
if (split[0] && split[1]) {
int origin[2] = {grid.origin(0) + size[0], grid.origin(1) + size[1]};
int ssize[2] = {size[2], size[3]};
extract_grid(origin, ssize);
}
emit gridToSend();
}
SendGrid popQueued(int i) { return _queues[i].dequeue(); }
bool hasQueuedData(int i) { return !_queues[i].isEmpty(); }
void setGridInfo(int i, const int size[2], const int origin[2]) {
_pieces[i].setSize(size);
_pieces[i].setOrigin(origin);
}
GridState state(int i) const { return _state[i]; }
void setState(GridState ns) { for(int i = 0; i < _state.size(); ++i) _state[i] = ns; }
void setState(GridState ns, int i) { _state[i] = ns; }
signals:
void gridToSend() {}
private:
QSemaphore _pieces_sem;
size_t _nb_pieces;
std::vector<T> _data;
size_t _size[2];
std::vector<GridInfo> _pieces;
QMutex _nb_pieces_lock;
std::vector<QQueue<SendGrid>> _queues;
std::vector<GridState> _state;
};
#endif /* GRID_HH */

Event Timeline