admesh refactoring: Using boost::object_pool for linked list memory
allocation.
This commit is contained in:
parent
590c290ede
commit
5fc465b7e8
3 changed files with 284 additions and 266 deletions
|
@ -28,8 +28,9 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/predef/other/endian.h>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/detail/endian.hpp>
|
||||
#include <boost/pool/object_pool.hpp>
|
||||
|
||||
#include "stl.h"
|
||||
|
||||
|
@ -46,7 +47,7 @@ struct HashEdge {
|
|||
// Index of this edge inside the facet with an index of facet_number.
|
||||
// If this edge is stored backwards, which_edge is increased by 3.
|
||||
int which_edge;
|
||||
struct HashEdge *next;
|
||||
HashEdge *next;
|
||||
|
||||
void load_exact(stl_file *stl, const stl_vertex *a, const stl_vertex *b)
|
||||
{
|
||||
|
@ -69,15 +70,15 @@ struct HashEdge {
|
|||
// Switch negative zeros to positive zeros, so memcmp will consider them to be equal.
|
||||
for (size_t i = 0; i < 6; ++ i) {
|
||||
unsigned char *p = (unsigned char*)(this->key + i);
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
#if BOOST_ENDIAN_LITTLE_BYTE
|
||||
if (p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0x80)
|
||||
// Negative zero, switch to positive zero.
|
||||
p[3] = 0;
|
||||
#else /* BOOST_LITTLE_ENDIAN */
|
||||
#else /* BOOST_ENDIAN_LITTLE_BYTE */
|
||||
if (p[0] == 0x80 && p[1] == 0 && p[2] == 0 && p[3] == 0)
|
||||
// Negative zero, switch to positive zero.
|
||||
p[0] = 0;
|
||||
#endif /* BOOST_LITTLE_ENDIAN */
|
||||
#endif /* BOOST_ENDIAN_LITTLE_BYTE */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ struct HashTableEdges {
|
|||
HashTableEdges(size_t number_of_faces) {
|
||||
this->M = (int)hash_size_from_nr_faces(number_of_faces);
|
||||
this->heads.assign(this->M, nullptr);
|
||||
this->tail = new HashEdge;
|
||||
this->tail = pool.construct();
|
||||
this->tail->next = this->tail;
|
||||
for (int i = 0; i < this->M; ++ i)
|
||||
this->heads[i] = this->tail;
|
||||
|
@ -124,80 +125,32 @@ struct HashTableEdges {
|
|||
for (int i = 0; i < this->M; ++ i) {
|
||||
for (HashEdge *temp = this->heads[i]; this->heads[i] != this->tail; temp = this->heads[i]) {
|
||||
this->heads[i] = this->heads[i]->next;
|
||||
delete temp;
|
||||
pool.destroy(temp);
|
||||
#ifndef NDEBUG
|
||||
++ this->freed;
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
}
|
||||
this->heads.clear();
|
||||
delete this->tail;
|
||||
pool.destroy(this->tail);
|
||||
this->tail = nullptr;
|
||||
}
|
||||
|
||||
void insert_edge(stl_file *stl, const HashEdge &edge, void (*match_neighbors)(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b))
|
||||
void insert_edge_exact(stl_file *stl, const HashEdge &edge)
|
||||
{
|
||||
int chain_number = edge.hash(this->M);
|
||||
HashEdge *link = this->heads[chain_number];
|
||||
if (link == this->tail) {
|
||||
// This list doesn't have any edges currently in it. Add this one.
|
||||
HashEdge *new_edge = new HashEdge(edge);
|
||||
#ifndef NDEBUG
|
||||
++ this->malloced;
|
||||
#endif /* NDEBUG */
|
||||
new_edge->next = this->tail;
|
||||
this->heads[chain_number] = new_edge;
|
||||
} else if (edges_equal(edge, *link)) {
|
||||
// This is a match. Record result in neighbors list.
|
||||
match_neighbors(stl, edge, *link);
|
||||
// Delete the matched edge from the list.
|
||||
this->heads[chain_number] = link->next;
|
||||
delete link;
|
||||
#ifndef NDEBUG
|
||||
++ this->freed;
|
||||
#endif /* NDEBUG */
|
||||
} else {
|
||||
// Continue through the rest of the list.
|
||||
for (;;) {
|
||||
if (link->next == this->tail) {
|
||||
// This is the last item in the list. Insert a new edge.
|
||||
HashEdge *new_edge = new HashEdge;
|
||||
#ifndef NDEBUG
|
||||
++ this->malloced;
|
||||
#endif /* NDEBUG */
|
||||
*new_edge = edge;
|
||||
new_edge->next = this->tail;
|
||||
link->next = new_edge;
|
||||
#ifndef NDEBUG
|
||||
++ this->collisions;
|
||||
#endif /* NDEBUG */
|
||||
break;
|
||||
}
|
||||
if (edges_equal(edge, *link->next)) {
|
||||
// This is a match. Record result in neighbors list.
|
||||
match_neighbors(stl, edge, *link->next);
|
||||
// Delete the matched edge from the list.
|
||||
HashEdge *temp = link->next;
|
||||
link->next = link->next->next;
|
||||
delete temp;
|
||||
#ifndef NDEBUG
|
||||
++ this->freed;
|
||||
#endif /* NDEBUG */
|
||||
break;
|
||||
}
|
||||
// This is not a match. Go to the next link.
|
||||
link = link->next;
|
||||
#ifndef NDEBUG
|
||||
++ this->collisions;
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
this->insert_edge(stl, edge, [stl](const HashEdge& edge1, const HashEdge& edge2) { record_neighbors(stl, edge1, edge2); });
|
||||
}
|
||||
|
||||
void insert_edge_nearby(stl_file *stl, const HashEdge &edge)
|
||||
{
|
||||
this->insert_edge(stl, edge, [stl](const HashEdge& edge1, const HashEdge& edge2) { match_neighbors_nearby(stl, edge1, edge2); });
|
||||
}
|
||||
|
||||
// Hash table on edges
|
||||
std::vector<HashEdge*> heads;
|
||||
HashEdge* tail;
|
||||
int M;
|
||||
boost::object_pool<HashEdge> pool;
|
||||
|
||||
#ifndef NDEBUG
|
||||
size_t malloced = 0;
|
||||
|
@ -216,12 +169,73 @@ private:
|
|||
return (it == primes.end()) ? primes.back() : *it;
|
||||
}
|
||||
|
||||
|
||||
// MatchNeighbors(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
|
||||
template<typename MatchNeighbors>
|
||||
void insert_edge(stl_file *stl, const HashEdge &edge, MatchNeighbors match_neighbors)
|
||||
{
|
||||
int chain_number = edge.hash(this->M);
|
||||
HashEdge *link = this->heads[chain_number];
|
||||
if (link == this->tail) {
|
||||
// This list doesn't have any edges currently in it. Add this one.
|
||||
HashEdge *new_edge = pool.construct(edge);
|
||||
#ifndef NDEBUG
|
||||
++ this->malloced;
|
||||
#endif /* NDEBUG */
|
||||
new_edge->next = this->tail;
|
||||
this->heads[chain_number] = new_edge;
|
||||
} else if (edges_equal(edge, *link)) {
|
||||
// This is a match. Record result in neighbors list.
|
||||
match_neighbors(edge, *link);
|
||||
// Delete the matched edge from the list.
|
||||
this->heads[chain_number] = link->next;
|
||||
pool.destroy(link);
|
||||
#ifndef NDEBUG
|
||||
++ this->freed;
|
||||
#endif /* NDEBUG */
|
||||
} else {
|
||||
// Continue through the rest of the list.
|
||||
for (;;) {
|
||||
if (link->next == this->tail) {
|
||||
// This is the last item in the list. Insert a new edge.
|
||||
HashEdge *new_edge = pool.construct();
|
||||
#ifndef NDEBUG
|
||||
++ this->malloced;
|
||||
#endif /* NDEBUG */
|
||||
*new_edge = edge;
|
||||
new_edge->next = this->tail;
|
||||
link->next = new_edge;
|
||||
#ifndef NDEBUG
|
||||
++ this->collisions;
|
||||
#endif /* NDEBUG */
|
||||
break;
|
||||
}
|
||||
if (edges_equal(edge, *link->next)) {
|
||||
// This is a match. Record result in neighbors list.
|
||||
match_neighbors(edge, *link->next);
|
||||
// Delete the matched edge from the list.
|
||||
HashEdge *temp = link->next;
|
||||
link->next = link->next->next;
|
||||
pool.destroy(temp);
|
||||
#ifndef NDEBUG
|
||||
++ this->freed;
|
||||
#endif /* NDEBUG */
|
||||
break;
|
||||
}
|
||||
// This is not a match. Go to the next link.
|
||||
link = link->next;
|
||||
#ifndef NDEBUG
|
||||
++ this->collisions;
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Edges equal for hashing. Edgesof different facet are allowed to be matched.
|
||||
static inline bool edges_equal(const HashEdge &edge_a, const HashEdge &edge_b)
|
||||
{
|
||||
return edge_a.facet_number != edge_b.facet_number && edge_a == edge_b;
|
||||
}
|
||||
};
|
||||
|
||||
static void record_neighbors(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
|
||||
{
|
||||
|
@ -407,6 +421,7 @@ static void match_neighbors_nearby(stl_file *stl, const HashEdge &edge_a, const
|
|||
}
|
||||
stl->stats.edges_fixed += 2;
|
||||
}
|
||||
};
|
||||
|
||||
// This function builds the neighbors list. No modifications are made
|
||||
// to any of the facets. The edges are said to match only if all six
|
||||
|
@ -445,7 +460,7 @@ void stl_check_facets_exact(stl_file *stl)
|
|||
edge.facet_number = i;
|
||||
edge.which_edge = j;
|
||||
edge.load_exact(stl, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
|
||||
hash_table.insert_edge(stl, edge, record_neighbors);
|
||||
hash_table.insert_edge_exact(stl, edge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +491,7 @@ void stl_check_facets_nearby(stl_file *stl, float tolerance)
|
|||
edge.which_edge = j;
|
||||
if (edge.load_nearby(stl, facet.vertex[j], facet.vertex[(j + 1) % 3], tolerance))
|
||||
// Only insert edges that have different keys.
|
||||
hash_table.insert_edge(stl, edge, match_neighbors_nearby);
|
||||
hash_table.insert_edge_nearby(stl, edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,7 +669,7 @@ void stl_fill_holes(stl_file *stl)
|
|||
edge.facet_number = i;
|
||||
edge.which_edge = j;
|
||||
edge.load_exact(stl, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
|
||||
hash_table.insert_edge(stl, edge, record_neighbors);
|
||||
hash_table.insert_edge_exact(stl, edge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,7 +719,7 @@ void stl_fill_holes(stl_file *stl)
|
|||
edge.facet_number = stl->stats.number_of_facets - 1;
|
||||
edge.which_edge = k;
|
||||
edge.load_exact(stl, &new_facet.vertex[k], &new_facet.vertex[(k + 1) % 3]);
|
||||
hash_table.insert_edge(stl, edge, record_neighbors);
|
||||
hash_table.insert_edge_exact(stl, edge);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <boost/pool/object_pool.hpp>
|
||||
|
||||
#include "stl.h"
|
||||
|
||||
static void reverse_facet(stl_file *stl, int facet_num)
|
||||
|
@ -120,8 +122,9 @@ void stl_fix_normal_directions(stl_file *stl)
|
|||
};
|
||||
|
||||
// Initialize linked list.
|
||||
stl_normal *head = new stl_normal;
|
||||
stl_normal *tail = new stl_normal;
|
||||
boost::object_pool<stl_normal> pool;
|
||||
stl_normal *head = pool.construct();
|
||||
stl_normal *tail = pool.construct();
|
||||
head->next = tail;
|
||||
tail->next = tail;
|
||||
|
||||
|
@ -168,7 +171,7 @@ void stl_fix_normal_directions(stl_file *stl)
|
|||
// If we haven't fixed this facet yet, add it to the list:
|
||||
if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
||||
// Add node to beginning of list.
|
||||
stl_normal *newn = new stl_normal;
|
||||
stl_normal *newn = pool.construct();
|
||||
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
||||
newn->next = head->next;
|
||||
head->next = newn;
|
||||
|
@ -189,7 +192,7 @@ void stl_fix_normal_directions(stl_file *stl)
|
|||
}
|
||||
stl_normal *temp = head->next; // Delete this facet from the list.
|
||||
head->next = head->next->next;
|
||||
delete temp;
|
||||
pool.destroy(temp);
|
||||
} else { // If we ran out of facets to fix: All of the facets in this part have been fixed.
|
||||
++ stl->stats.number_of_parts;
|
||||
if (checked >= stl->stats.number_of_facets)
|
||||
|
@ -211,8 +214,8 @@ void stl_fix_normal_directions(stl_file *stl)
|
|||
}
|
||||
}
|
||||
|
||||
delete head;
|
||||
delete tail;
|
||||
pool.destroy(head);
|
||||
pool.destroy(tail);
|
||||
}
|
||||
|
||||
void stl_fix_normal_values(stl_file *stl)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/detail/endian.hpp>
|
||||
#include <boost/predef/other/endian.h>
|
||||
|
||||
#include "stl.h"
|
||||
|
||||
|
@ -114,7 +114,7 @@ bool stl_print_neighbors(stl_file *stl, char *file)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef BOOST_LITTLE_ENDIAN
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
// Swap a buffer of 32bit data from little endian to big endian and vice versa.
|
||||
void stl_internal_reverse_quads(char *buf, size_t cnt)
|
||||
{
|
||||
|
@ -141,11 +141,11 @@ bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
|||
#define SEEK_SET 0
|
||||
#endif
|
||||
fseek(fp, LABEL_SIZE, SEEK_SET);
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
#if BOOST_ENDIAN_LITTLE_BYTE
|
||||
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
||||
for (const stl_facet &facet : stl->facet_start)
|
||||
fwrite(&facet, SIZEOF_STL_FACET, 1, fp);
|
||||
#else /* BOOST_LITTLE_ENDIAN */
|
||||
#else /* BOOST_ENDIAN_LITTLE_BYTE */
|
||||
char buffer[50];
|
||||
// Convert the number of facets to little endian.
|
||||
memcpy(buffer, &stl->stats.number_of_facets, 4);
|
||||
|
@ -157,7 +157,7 @@ bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
|||
stl_internal_reverse_quads(buffer, 48);
|
||||
fwrite(buffer, SIZEOF_STL_FACET, 1, fp);
|
||||
}
|
||||
#endif /* BOOST_LITTLE_ENDIAN */
|
||||
#endif /* BOOST_ENDIAN_LITTLE_BYTE */
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue