fair_queue: struct offsetof() only with POD struct

In C++ offsetof() is not specified on non-POD structs
(eg. having methods or non-POD members).
This commit is contained in:
Michael Davidsaver
2015-12-20 09:51:48 -05:00
parent db002e51c8
commit 837c10a003
+22 -8
View File
@@ -49,7 +49,15 @@ public:
typedef std::tr1::shared_ptr<T> value_type;
class epicsShareClass entry {
ELLNODE node;
/* In c++, use of ellLib (which implies offsetof()) should be restricted
* to POD structs. So enode_t exists as a POD struct for which offsetof()
* is safe and well defined. enode_t::self is used in place of
* casting via CONTAINER(penode, entry, enode)
*/
struct enode_t {
ELLNODE node;
entry *self;
} enode;
unsigned Qcnt;
value_type holder;
#ifndef NDEBUG
@@ -61,16 +69,20 @@ public:
entry(const entry&);
entry& operator=(const entry&);
public:
entry() :node(), Qcnt(0), holder()
entry() :Qcnt(0), holder()
#ifndef NDEBUG
, owner(NULL)
#endif
{
node.next = node.previous = NULL;
enode.node.next = enode.node.previous = NULL;
enode.self = this;
}
~entry() {
// nodes should be removed from the list before deletion
assert(!node.next && !node.previous && !owner);
assert(!enode.node.next && !enode.node.previous);
#ifndef NDEBUG
assert(!owner);
#endif
}
};
@@ -111,7 +123,7 @@ public:
assert(P->owner==NULL);
P->owner = this;
P->holder = ent; // the list will hold a reference
ellAdd(&list, &P->node); // push_back
ellAdd(&list, &P->enode.node); // push_back
} else
assert(P->owner==this);
}
@@ -124,16 +136,18 @@ public:
ELLNODE *cur = ellGet(&list); // pop_front
if(cur) {
entry *P = CONTAINER(cur, entry, node);
typedef typename entry::enode_t enode_t;
enode_t *PN = CONTAINER(cur, enode_t, node);
entry *P = PN->self;
assert(P->owner==this);
assert(P->Qcnt>0);
if(--P->Qcnt==0) {
P->node.previous = P->node.next = NULL;
PN->node.previous = PN->node.next = NULL;
P->owner = NULL;
ret.swap(P->holder);
} else {
ellAdd(&list, &P->node); // push_back
ellAdd(&list, &P->enode.node); // push_back
ret = P->holder;
}