Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm working on a hierarchical Entity-Component System. It's called hierarchical
because an Entity might be composed of several Entities.
My hierarchy structure is implemented as several linked lists. Although, I'm not relying on several std::list or std::forward_list. Actually, I have two vectors: 1) maps an Entity to its first child; 2) maps a child to its next sibling.
I'd like to create a ranges::view on this structure, but it seems I'm forgetting something.
I'd like to use the range this way (Complete Code on GitHub):
TEST_CASE("Range adaptors")
{
auto parentSystem = System<Test::Parent>{};
auto childSystem = System<Test::Child>{};
auto parent0 = parentSystem.add();
auto parent1 = parentSystem.add();
LeftMapped<Test::Parent, System, Test::Child, System> leftMapped(parentSystem, childSystem);
leftMapped.addChild(parent0, childSystem.add());
leftMapped.addChild(parent0, childSystem.add());
leftMapped.addChild(parent0, childSystem.add());
leftMapped.addChild(parent1, childSystem.add());
// HERE \/
ranges::for_each(leftMapped.children(parent0), [](Test::Child child)
{
std::cout << static_cast<Base>(child).id() << std::endl;
});
}
And of course, make it pipeable for working with views and actions compatible with forward range (I'm not so used to the Concepts idiom).
This is the part of the code I want to adapt:
// A composition should inherit Left Mapped when it is necessary O(1) mapping from parent to children.
template <typename ParentType, template <typename> class ParentSystemType, typename ChildType, template <typename> class ChildSystemType>
class LeftMapped
{
public:
LeftMapped(ParentSystemType<ParentType>& parent, ChildSystemType<ChildType>& child):
m_firstChild(makeProperty<ChildType>(parent)),
m_nextSibling(makeProperty<ChildType>(child))
{
}
ChildType firstChild(ParentType parent) const
{
return m_firstChild[parent];
}
ChildType nextSibling(ChildType child) const
{
return m_nextSibling[child];
}
void firstChild(ParentType parent, ChildType child)
{
m_firstChild[parent] = child;
}
void nextSibling(ChildType child, ChildType next)
{
m_nextSibling[child] = next;
}
void addChild(ParentType parent, ChildType child)
{
m_nextSibling[child] = m_firstChild[parent];
m_firstChild[parent] = child;
}
// HERE \/ I don't know how to properly adapt my container.
class ChildrenView : public ranges::view_facade<ChildrenView> {
friend ranges::range_access;
const LeftMapped& mapped;
const ParentType parent;
struct cursor
{
const LeftMapped& mapped;
ChildType current;
decltype(auto) read() const
{
return current;
}
void next()
{
current = mapped.nextSibling(current);
}
bool equal(ranges::default_sentinel) const {
return current == ChildType{};
}
};
cursor begin_cursor() {
return {mapped, mapped.firstChild(parent)};
}
public:
ChildrenView() = default;
explicit ChildrenView(const LeftMapped& mapped, ParentType parent)
: mapped(mapped),
parent(parent)
{}
};
auto children(ParentType parent) const
{
return ChildrenView(*this, parent);
}
private:
Property<ParentType, ChildType, ParentSystemType> m_firstChild;
Property<ChildType, ChildType, ChildSystemType> m_nextSibling;
};
The first thing that jumped out at me was that you have reference data members both in ChildrenView and in ChildrenView::cursor. That makes those types non-assignable, which range-v3 requires. Try changing them to pointers or std::reference_wrappers, and see if that gets you any closer.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
Improve this question
I am interacting with (not-owned-by-me) API that takes a raw pointer to Thing and sometimes deletes it on its own, basically something like:
bool foo(Thing* ptr) {
if (/* some condition */) {
delete ptr;
return true;
} else {
return false;
}
}
Now I'm writing some tests that on a side interact with this method, and I would want to avoid writing typical T* ptr = new Thing(); bool res = foo(ptr); /* real test */; if (!res) { delete ptr; }; spread across the code.
So I've created some kind of "tracking-wrapper" that looks like this:
template <typename T> class Holder {
public:
// Subclass of Z where the dtor will just update Holder's state.
template <typename Z> class Helper : public Z {
public:
Helper(Holder<Z>& holder): holder_{holder} {}
virtual ~Helper() { holder_.markDeleted(); }
private:
Holder<Z>& holder_;
};
~Holder() {
if (!deleted_) { delete ptr; }
}
void markDeleted() { deleted_ = true; }
T* data() { return ptr; }
private:
bool deleted_ = false;
T* ptr = new Helper<T>(*this);
};
so basically I can use it like this:
Holder<Thing> h;
foo(h.data());
with Holder's destructor doing the cleanup of Thing* if necessary.
Is there any alternative for this custom code (e.g. in standard library)?
We can assume the following:
T's destructor is virtual,
T does not require arguments to be constructed,
we cannot modify T.
auto h = std::make_unique<T>();
if (foo(h.get())) {
h.release(); // already deleted, so we don't own it
}
(And this is why implementations shouldn't mark unique_ptr::release as [[nodiscard]])
I'm writing some arduino libraries and would like to improve readability / add some syntactic suggar.
What I would like to do is create objects on the heap in a way that would look like:
Panel panel(
Button( 1 ).on( Click( clickfunc ) ),
Button( 2 ).on( Hold( holdfunc, 1000 ) )
);
(Button, Click, Hold are all classes and internally managed via linked lists (so they aren't constant.))
I tried writing it this way but I stumbled over problems with references to temporaries.
Currently I can use:
Button button1( 1 ), button2( 2 );
Click theClick( clickFunction );
Hold theHold( holdFunction, 1000 );
Panel( button1.on( theClick ), button2.on( theHold ) );
but this is not nearly as readable as the above and tends to be error-prone because you have to stay alert and don't put e.g. theClick on another button which would break the linked list.
Some heavily shortened excerpts from the classes like they are now.
class Button {
Handler *_first;
Button( int no ){...}
Button & on( Handler &handler ){
handler._next = _first;
_first = &handler;
return *this;
}
void handle( int oldValue, int newValue ) {
Handler *handler;
for( handler = _first; handler; handler = handler->_next ){
handler->handle( oldValue, newValue );
}
}
}
class Handler {
Handler *_next;
virtual void handle( int oldValue, int newValue ) = 0;
...
}
class Click : public Handler {
...
}
class Hold : public Handler {
...
}
Note that this doesn't necessarily needs to stay this way. The goal is to provide a library where its user doesn't need to know to much about its inner working but has a simple/clean interface.
If you have problem with dangling references with the code above, I suspect you are making a linked list that create references (or pointer) that points to those element on the stack.
I suspect also that your signature looks like this:
Button& on(const Event& event) { /* ... */ }
To help you with your problem, I suggest to change the signature of your on function to something like this:
template<typename EventType>
Button& on(EventType&& event) {
}
That way, you can actually forward the object into the heap, and use some form of type easure to put it into your linked list:
struct Handler {
virtual void handle(int oldValue, int newValue) = 0;
// Defaulted virtual destructor
virtual ~Handler() = default;
};
template<typename T>
struct HandlerImpl : Handler {
// constructors
HandlerImpl(T h) : handler{std::forward<T>(h)} {}
void handle(int oldValue, int newValue) {
handler.handle(oldValue, newValue);
}
// We use the compiler generated destructor
private:
remove_rvalue_reference_t<T> handler;
};
template<typename HandlerType>
Button& on(HandlerType&& event) {
// See the code example below
}
What changes in the rest of your code?
Well, now both syntax you posted are supported. The first syntax will move and hold the variable. The second syntax will only hold references to the events and will assume that the lifetime of the event are equal or bigger of those of the button.
Also, Click and Hold don't need to extend any class nor need virtual function or virtual destructors.
If you don't want the second syntax to hold references and use copy instead, replace remove_rvalue_reference_t by std::remove_reference_t.
This pattern I showed you can be applied for Button, and for any widget type you want.
Here's how remove_rvalue_reference_t is implemented:
template<typename T> struct remove_rvalue_reference { using type = T; };
template<typename T> struct remove_rvalue_reference<T&&> { using type = T; };
template<typename T> using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;
Since you have posted an example of your code, I can now help you transform it so it can work with the code above.
First, liked list are slow, and hand rolled liked list are worse. I strongly suggest you to use std::vector. Secondly, std::unique_ptr is the preferred way to hold owning pointers. So, just by following this and the steps mentioned above, your code should look like this:
struct Button {
std::vector<std::unique_ptr<Handler>> _handlers;
Button(int no) { /* ... */ }
// This function will work for any type that
// happen to have an `handle` function.
template<typename H> // <--- H is the handler type
Button& on(H&& handler) { // H&& in this case means forwarding reference.
// We add (emplace) a new HandlerImpl, allocated on the heap using `std::make_unique`
_handlers.emplace_back(
std::make_unique<HandlerImpl<H>>(std::forward<H>(handler))
);
return *this;
}
void handle(int oldValue, int newValue) {
// We use a range for loop here to iterate on the vector
for (auto&& handler : _handlers) {
handler->handle(oldValue, newValue);
}
}
};
// We do not extends anything
struct Click {
// Notice that the function is not virtual
void handle(int oldVal, int newVal) {/* ... */}
};
struct Hold {
void handle(int oldVal, int newVal) {/* ... */}
};
Here's a live example at Coliru
I have the following implementation of interlocked singly linked list using C++11 atomics:
struct notag {};
template<class T, class Tag=notag>
struct s_list_base
{
};
template<class T, class Tag = notag>
struct s_list : s_list_base<T, Tag>
{
s_list_base<T, Tag> *next_ptr;
};
template<bool auto_destruct, class T, class Tag = notag>
class atomic_s_list
{
struct s_head : s_list_base<T, Tag>
{
std::atomic<s_list_base<T, Tag > *> next_ptr { this };
};
using LinkType = s_list<T, Tag> *;
s_head head;
public:
atomic_s_list() = default;
atomic_s_list(const atomic_s_list &) = delete;
atomic_s_list &operator =(const atomic_s_list &) = delete;
~atomic_s_list()
{
clear();
}
void clear() noexcept
{
if (auto_destruct)
{
T *item;
do
{
item = pop();
delete item;
} while (item);
}
else
head.next_ptr = &head;
}
void push(T *pItem) noexcept
{
auto p = static_cast<LinkType>(pItem);
auto phead = head.next_ptr.load(std::memory_order_relaxed);
do
{
p->next_ptr = phead;
} while (!head.next_ptr.compare_exchange_weak(phead, p));
}
T *pop() noexcept
{
auto result = head.next_ptr.load(std::memory_order_relaxed);
while (!head.next_ptr.compare_exchange_weak(result, static_cast<LinkType>(result)->next_ptr))
;
return result == &head ? nullptr : static_cast<T *>(result);
}
};
The problem is that in real program I have several concurrently running threads that take an object from this list with pop, work with it and then put it back with push and it seems like I have a race when sometimes two threads end up getting the same object from a list.
I have tried to make a simple example out of that program to illustrate a race.
Here it is:
struct item : s_list<item>
{
std::atomic<int> use{ 0 };
};
atomic_s_list<true, item> items;
item *allocate()
{
auto *result = items.pop();
if (!result)
result = new item;
return result;
}
void free(item *p)
{
items.push(p);
}
int main()
{
using namespace std::chrono_literals;
static const int N = 20;
std::vector<std::thread> threads;
threads.reserve(N);
for (int i = 0; i < N; ++i)
{
threads.push_back(std::thread([&]
{
while (true)
{
auto item = allocate();
if (0 != item->use.fetch_add(1, std::memory_order_relaxed))
std::terminate();
item->use.fetch_sub(1, std::memory_order_relaxed);
free(item);
}
}));
}
std::this_thread::sleep_for(20min);
}
So the question is: is this implementation of interlocked singly-linked list correct?
After more research I can confirm that I face with an ABA problem.
It appears like no one should ever trust this simple interlocked singly linked list implementation on modern hardware (with lots of hardware threads) and highly-contended interlocked lists.
After considering implementing the tricks described in Wikipedia article, I have decided to use boost implementation (see boost::lockfree::stack) as it seems like having good efforts on fighting ABA problem.
For now my test code does not fail, and neither does the original program.
Is not a correct implementation!
thread A and thread B call pop; A and B get the same "result" -> head.next_ptr
thread A modify the memory.
thread B read "result->next_ptr" get INCORRECT DATA
thread A call push. head.next_ptr == "result" NOW!
thread B call compare_exchange_weak; head.next_ptr update with the INCORRECT DATA
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
As a practice program after learning C++, I am developing a text-based game. I am using object-oriented programming style for handling the worlds/their objects. Here's the necessary information about their definitions:
class Object
{
private:
unsigned int id;
public:
unsigned int getID() const { return id; }
};
class TakeableObject: public Object
{
...
};
class EdibleObject: public TakeableObject
{
private:
float healthEffect;
float staminaEffect;
public:
float getHealthEffect() const { return healthEffect; }
float getStaminaEffect() const { return staminaEffect; }
};
class Player
{
private:
float health;
float stamina;
TakeableObject inventory[256];
public:
eat(const EdibleObject* o)
{
health += o->getHealthEffect();
stamina += o->getStaminaEffect();
}
eat(int id)
{
if (inventory[id] == NULL)
throw "No item with that ID!";
eat((EdibleObject) inventory[id]);
inventory[id] = NULL;
}
};
So my question is - in Player::eat(int), is there a way I can make sure the Object at Player::inventory[id] is an EdibleObject (perhaps through exception handling?)
User dynamic cast to check the object type at runtime.
Or you can use a virtual function with default definition in parent and can update it as per your requirement in derived classes.
Instead of eat((EdibleObject) inventory[id]); use the following
EdibleObject *temp = dynamic_cast<EdibleObject *>( &inventory[id] );
if(temp) { eat(*temp); }
else { /* Handling */ }
Your code suffers Object splicing, make sure to get rid of that first.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to detect whether there is a specific member variable in class?
I'm adding features to a C++ library. A thing that'd come in handy was to check if a certain member exists in a struct (it exisits depending on the library version - unfortunately there is no "version" parameter in the library).
Here is a simplified example of what I'd like to do:
struct options {
int option1;
std::string option2;
float option3; // might be included or not
options();
void random_method();
}
options::options() {
option1 = 1;
option2 = "foo";
if( EXISTS(option3) ) { // Pseudo-Code -> can I do that at all?
option3 = 1.1;
}
}
You could implement a pure virtual function in the parent structure and have the children implement it.
struct Parent
{
virtual bool has_option(OPTION) const = 0;
};
struct Car : public Parent
{
bool has_option(OPTION op) const
{
bool result = false;
if (op == MOON_ROOF)
{
result = true;
}
return result;
}
};