Skip to content

Commit

Permalink
Merge pull request #8 from physarumAdv/move_copy_mechanisms
Browse files Browse the repository at this point in the history
Move/copy mechanisms
  • Loading branch information
tanya-kta authored Sep 12, 2020
2 parents 485f831 + dfa8b2f commit 7f658c5
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 54 deletions.
39 changes: 35 additions & 4 deletions src/Face.cu
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Face.cuh"
#include "MapNode.cuh"
#include "Polyhedron.cuh"
#include "common.cuh"


__device__ SpacePoint calculate_normal(const SpacePoint *vertices)
Expand All @@ -9,19 +10,49 @@ __device__ SpacePoint calculate_normal(const SpacePoint *vertices)
return normal / get_distance(normal, origin);
}


__device__ Face::Face(const SpacePoint *vertices, int n_of_vertices) :
vertices(malloc_and_copy(vertices, n_of_vertices)), n_of_vertices(n_of_vertices),
normal(calculate_normal(vertices)), node(nullptr)
{

}

__device__ Face::Face(const Face &other) :
vertices(malloc_and_copy(other.vertices, other.n_of_vertices)),
n_of_vertices(other.n_of_vertices),
normal(other.normal), node(other.node)
__device__ Face &Face::operator=(const Face &other)
{
if(this != &other)
{
vertices = malloc_and_copy(other.vertices, other.n_of_vertices);
n_of_vertices = other.n_of_vertices;
normal = other.normal;
node = nullptr;
}
return *this;
}

__device__ Face::Face(const Face &other)
{
*this = other;
}

__device__ Face &Face::operator=(Face &&other) noexcept
{
if(this != &other)
{
swap(vertices, other.vertices);
swap(n_of_vertices, other.n_of_vertices);
swap(normal, other.normal);
swap(node, other.node);
}

return *this;
}

__device__ Face::Face(Face &&other) noexcept
{
vertices = nullptr;

*this = std::move(other);
}

__device__ Face::~Face()
Expand Down
40 changes: 37 additions & 3 deletions src/Face.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


#include "SpacePoint.cuh"
#include "common.cuh"


/**
* Returns the normal to faces defined by vertices
Expand All @@ -19,7 +19,12 @@ class MapNode;

class Polyhedron;

/// Object describing a polyhedron face
/**
* Object describing a polyhedron face
*
* @warning <b>Before using the class, please, carefully read documentation for both copy and move constructors and
* assignment operators!</b>
*/
class Face
{
public:
Expand All @@ -37,9 +42,38 @@ public:
*/
__device__ Face(const SpacePoint *vertices, int n_of_vertices);

/// `Face` object copy constructor
/**
* `Face` object copy assignment operator
*
* @warning When copying `Face` object, its `node` field is <b>not</b> copied, but is set to `nullptr`, which means
* the new `Face` won't have a node attached. Please, be careful
*/
__device__ Face &operator=(const Face &other);

/**
* `Face` object copy constructor
*
* @warning When copying `Face` object, its `node` field is <b>not</b> copied, but is set to `nullptr`, which means
* the new `Face` won't have a node attached. Please, be careful
*/
__device__ Face(const Face &other);

/**
* `Face` object move assignment operator
*
* @warning If the being moved `Face`'s field `node` is not `nullptr`, this might mean there is a node pointing
* to the `Face` being moved, so moving it will <b>invalidate</b> the pointers set at `*node`
*/
__device__ Face &operator=(Face &&other) noexcept;

/**
* `Face` object move constructor
*
* @warning If the being moved `Face`'s field `node` is not `nullptr`, this might mean there is a node pointing
* to the `Face` being moved, so moving it will <b>invalidate</b> the pointers set at `*node`
*/
__device__ Face(Face &&other) noexcept;

/// Destructs a `Face` object
__device__ ~Face();

Expand Down
37 changes: 32 additions & 5 deletions src/MapNode.cu
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,37 @@


__device__ MapNode::MapNode(Polyhedron *polyhedron, Face *polyhedron_face, SpacePoint coordinates) :
polyhedron(polyhedron), trail(0), contains_food(false), coordinates(coordinates),
polyhedron_face(polyhedron_face), left(nullptr), top(nullptr), right(nullptr), bottom(nullptr)
trail(0), temp_trail(0), left(nullptr), top(nullptr), right(nullptr), bottom(nullptr), polyhedron(polyhedron),
polyhedron_face(polyhedron_face), coordinates(coordinates), contains_food(false), particle(nullptr)
{}

__host__ __device__ MapNode &MapNode::operator=(MapNode &&other) noexcept
{
if(this != &other)
{
swap(polyhedron, other.polyhedron);
swap(trail, other.trail);
swap(temp_trail, other.temp_trail);
swap(left, other.left);
swap(top, other.top);
swap(right, other.right);
swap(bottom, other.bottom);
swap(polyhedron_face, other.polyhedron_face);
swap(coordinates, other.coordinates);
swap(contains_food, other.contains_food);
swap(particle, other.particle);
}

return *this;
}

__host__ __device__ MapNode::MapNode(MapNode &&other) noexcept
{
particle = nullptr;

*this = std::move(other);
}

__device__ MapNode::~MapNode()
{
delete particle;
Expand All @@ -27,7 +54,7 @@ __device__ MapNode::~MapNode()
*/
__device__ inline bool set_mapnode_neighbor(MapNode **target, MapNode *value)
{
static_assert(sizeof(target) <= sizeof(unsigned long long *), "I think, I can't safely cast `MapNode **` to"
static_assert(sizeof(target) <= sizeof(unsigned long long *), "I think, I can't safely cast `MapNode **` to "
"`unsigned long long *`");

if(value == nullptr)
Expand Down Expand Up @@ -109,7 +136,7 @@ __device__ bool MapNode::does_contain_particle() const

__device__ bool MapNode::attach_particle(Particle *p)
{
static_assert(sizeof(&particle) <= sizeof(unsigned long long *), "I think, I can't safely cast `Particle **` to"
static_assert(sizeof(&particle) <= sizeof(unsigned long long *), "I think, I can't safely cast `Particle **` to "
"`unsigned long long *`");

return nullptr == (Particle *)atomicCAS((unsigned long long *)&particle, (unsigned long long)nullptr,
Expand All @@ -128,7 +155,7 @@ __device__ void MapNode::detach_particle()

__device__ bool MapNode::detach_particle(Particle *p)
{
static_assert(sizeof(&particle) <= sizeof(unsigned long long *), "I think, I can't safely cast `Particle **` to"
static_assert(sizeof(&particle) <= sizeof(unsigned long long *), "I think, I can't safely cast `Particle **` to "
"`unsigned long long *`");

return p == (Particle *)atomicCAS((unsigned long long *)&particle, (unsigned long long)p,
Expand Down
47 changes: 23 additions & 24 deletions src/MapNode.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,31 @@ public:
*/
__device__ MapNode(Polyhedron *polyhedron, Face *polyhedron_face, SpacePoint coordinates);

/// Forbids copying `MapNode` objects
/**
* `MapNode` object copy assignment operator (deleted)
*
* Deleted because the need to copy a `MapNode` is a rather special case and can be done with other methods, while
* an accidental copying of a `MapNode` can result into unexpected things (for example, when copying a `MapNode`
* the `Particle` from the original node shouldn't be copied, and unwanted copy may create an impression that
* there is no particle in a node, but in fact it will be checking a copy of an original node)
*/
__host__ __device__ MapNode &operator=(const MapNode &other) = delete;

/**
* `MapNode` object copy constructor (deleted)
*
* Deleted because the need to copy a `MapNode` is a rather special case and can be done with other methods, while
* an accidental copying of a `MapNode` can result into unexpected things (for example, when copying a `MapNode`
* the `Particle` from the original node shouldn't be copied, and unwanted copy may create an impression that
* there is no particle in a node, but in fact it will be checking a copy of an original node)
*/
__host__ __device__ MapNode(const MapNode &) = delete;

/// Move assignment operator
__host__ __device__ MapNode &operator=(MapNode &&other) noexcept
{
swap(polyhedron, other.polyhedron);
swap(trail, other.trail);
swap(temp_trail, other.temp_trail);
swap(left, other.left);
swap(right, other.right);
swap(top, other.top);
swap(bottom, other.bottom);
swap(polyhedron_face, other.polyhedron_face);
swap(coordinates, other.coordinates);
swap(contains_food, other.contains_food);
swap(particle, other.particle);
return *this;
}

/// Move constructor for MapNode
__host__ __device__ MapNode(MapNode &&other) noexcept
{
particle = nullptr;
*this = std::move(other);
}
/// `MapNode` object move assignment operator
__host__ __device__ MapNode &operator=(MapNode &&other) noexcept;

/// `MapNode` object move constructor
__host__ __device__ MapNode(MapNode &&other) noexcept;

/// Destructs a `MapNode` object
__device__ ~MapNode();
Expand Down
35 changes: 32 additions & 3 deletions src/Particle.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,38 @@ public:
*/
__device__ Particle(MapNode *map_node, double angle);

/// Forbids copying `Particle` objects
/**
* `Particle` object copy assignment operator (deleted)
*
* Deleted because copying a `Particle` object does not make sense in the model. (when implementing a fission you
* should construct each new `Particle` object from scratch)
*/
__host__ __device__ Particle &operator=(const Particle &) = delete;

/**
* `Particle` object copy constructor (deleted)
*
* Deleted because copying a `Particle` object does not make sense in the model. (when implementing a fission you
* should construct each new `Particle` object from scratch)
*/
__host__ __device__ Particle(const Particle &) = delete;

/**
* `Particle` object move assignment operator (deleted)
*
* Deleted because `Particle` should be created by a `MapNode` which saves pointers to the created particle. Moving
* a `Particle` invalidates the `MapNode`'s pointer
*/
__host__ __device__ Particle &operator=(Particle &&other) noexcept = delete;

/**
* `Particle` object move constructor (deleted)
*
* Deleted because `Particle` should be created by a `MapNode` which saves pointers to the created particle. Moving
* a `Particle` invalidates the `MapNode`'s pointer
*/
__host__ __device__ Particle(Particle &&other) noexcept = delete;


/**
* Moves particle in the direction in which the particle is rotated
Expand Down Expand Up @@ -107,8 +136,8 @@ private:


/**
* Flag showing whether the particle was processed during current iteration (should be changed with `capture` and
* `release` methods)
* Flag showing whether the particle was processed during current simulation iteration (should only be updated with
* `capture` and `release` methods)
*/
bool is_captured = false;
};
Expand Down
53 changes: 49 additions & 4 deletions src/Polyhedron.cu
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Polyhedron.cuh"
#include "common.cuh"


__device__ Polyhedron::Polyhedron(Face *faces, int n_of_faces) :
Expand All @@ -7,11 +8,45 @@ __device__ Polyhedron::Polyhedron(Face *faces, int n_of_faces) :

}

__device__ Polyhedron &Polyhedron::operator=(const Polyhedron &other)
{
if(this != &other)
{
faces = malloc_and_copy(other.faces, other.n_of_faces);
n_of_faces = other.n_of_faces;
}
return *this;
}

__device__ Polyhedron::Polyhedron(const Polyhedron &other)
{
*this = other;
}

__device__ Polyhedron &Polyhedron::operator=(Polyhedron &&other) noexcept
{
if(this != &other)
{
swap(faces, other.faces);
swap(n_of_faces, other.n_of_faces);
}

return *this;
}

__device__ Polyhedron::Polyhedron(Polyhedron &&other) noexcept
{
faces = nullptr;

*this = std::move(other);
}

__device__ Polyhedron::~Polyhedron()
{
free((void *)faces);
}


__device__ Face *Polyhedron::find_face_by_point(SpacePoint point) const
{
for(int i = 0; i < n_of_faces; ++i)
Expand All @@ -25,6 +60,16 @@ __device__ Face *Polyhedron::find_face_by_point(SpacePoint point) const
return &faces[0];
}

__device__ Face *Polyhedron::get_faces() const
{
return faces;
}

__device__ int Polyhedron::get_n_of_faces() const
{
return n_of_faces;
}


__device__ bool does_edge_belong_to_face(SpacePoint a, SpacePoint b, const Face *face)
{
Expand All @@ -41,12 +86,12 @@ __device__ bool does_edge_belong_to_face(SpacePoint a, SpacePoint b, const Face

__device__ Face *find_face_next_to_edge(int vertex_id, Face *current_face, Polyhedron *polyhedron)
{
for(int i = 0; i < polyhedron->n_of_faces; ++i)
if(polyhedron->faces[i] != *current_face &&
for(int i = 0; i < polyhedron->get_n_of_faces(); ++i)
if(polyhedron->get_faces()[i] != *current_face &&
does_edge_belong_to_face(current_face->get_vertices()[vertex_id],
current_face->get_vertices()[vertex_id + 1],
&polyhedron->faces[i]))
return &polyhedron->faces[i];
&polyhedron->get_faces()[i]))
return &polyhedron->get_faces()[i];
return current_face;
}

Expand Down
Loading

0 comments on commit 7f658c5

Please sign in to comment.