Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch updates and readers #91

Open
tusooa opened this issue Jan 2, 2021 · 4 comments
Open

Batch updates and readers #91

tusooa opened this issue Jan 2, 2021 · 4 comments

Comments

@tusooa
Copy link
Contributor

tusooa commented Jan 2, 2021

Consider the following program:

#include <lager/store.hpp>
#include <lager/reader.hpp>
#include <lager/event_loop/boost_asio.hpp>

#include <thread>
#include <boost/asio.hpp>

#include <iostream>

using Model = int;
using Action = int;
Model update(Model orig, Action add)
{
    return orig + add;
}

int main()
{
    boost::asio::io_context io;
    auto store = lager::make_store<Action>(
        Model{},
        &update,
        lager::with_boost_asio_event_loop{io.get_executor()});

    auto reader = lager::reader<Model>(store);

    lager::watch(reader,
                 [](Model m) {
                     std::cerr << "model is now: " << m << std::endl;
                 });

    auto guard = boost::asio::executor_work_guard(io.get_executor());

    std::thread([&] { io.run(); }).detach();

    for (int i = 0; i < 100; ++i) {
        store.dispatch(1);
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

One may expect that upon running this one will get 100 lines of output from 1 to 100. But this is actually not the case. It actually only outputs starting from ~50 and will sometimes skip values.

Is this expected? From my understanding, the dispatch() is just a call to event loop's post(), which should run the whole push_down() process, including those notify()s, which basically call the connected callback function, in io_context's thread (which we detach()ed earlier). If this is correct, there should not be any data races and no output should be skipped... but it is not the case.

The thing behind this is that I am trying to use store as an event listener (https://gitlab.com/kazv/libkazv/-/blob/servant/src/eventemitter/lagerstoreeventemitter.hpp). Or does this idea just not work?

@arximboldi
Copy link
Owner

It is true that current implementation of observing via cursors may not expose every value when two actions happen very close in time. This is not really a data race. This works for UI since you are only interested in the "current" value and not every single intermediate value.

I think this could be changed if you have a good use-case for observing every single intermediate value. I can guide you through the code on why this is happening and we can discuss ways to change it.

@arximboldi
Copy link
Owner

Btw, as a workaround, to use the store as an event listener, you can call your callbacks in an effect returned by the update function. The effect would be guaranteed to be called every time.

@tusooa
Copy link
Contributor Author

tusooa commented Jan 11, 2021

Btw, as a workaround, to use the store as an event listener, you can call your callbacks in an effect returned by the update function. The effect would be guaranteed to be called every time.

Thank you, calling it in effects does help (although leads to more code lol).

@arximboldi
Copy link
Owner

I'd be happy to have a tag for the store<> type, like now we have automatic_tag and transactional_tag, maybe we could have something like discrete_tag (maybe there is a better name?) for the behavior of ensuring that every update() causes a notification.

jacktony980 pushed a commit to jacktony980/sendingcpp that referenced this issue May 15, 2023
Simply using a reader will not always call the callbacks
after emitting an event, which means we will frequently
miss events (arximboldi/lager#91).
This commit calls the callbacks in the effect returned by
the reducer instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants