Skip to content
Snippets Groups Projects
Commit bae710b4 authored by Sebastian Hahta's avatar Sebastian Hahta
Browse files

fix deadlock

parent ceb21270
No related branches found
No related tags found
1 merge request!316Resolves #343 GUI and Frame Refactor
Pipeline #28586 failed
......@@ -132,10 +132,10 @@ struct Aggregator {
* generates discrete blocks of data with a timestamp, these blocks are
* encapsulated in a frame that has any number of channels. A `Frame` must be
* constructed from a `Pool` object so that memory can be reused.
*
*
* It can be moved around but not copied since the quantity of data involved in
* a frame is huge.
*
*
* A frame goes through the following stages:
* 1) Creation from reused memory in `Pool`
* 2) Populate with incoming initial data/changes (from stream)
......@@ -143,28 +143,28 @@ struct Aggregator {
* 4) Create any new data such as new video frames
* 5) Flush the data to transmit or save, becomes readonly
* 6) Release memory to `Pool`
*
*
* A channel stores one particular element of data of a specified type. To write
* to a channel the `create` or `set` methods must be used, this will mark the
* channel as changed but can only occur before the frame is flushed and
* readonly. A `get` method allows const access to the data as long as the
* channel exists.
*
*
* On change events are triggered when `store` occurs, whereas on flush events
* occur after flush. Both of these may occur on destruction if the frame was
* not stored or flushed before destruction.
*
*
* Some channels may fail `hasChannel` but still be marked as `available`. This
* will be due to the data not being transmitted or encoded until requested.
*
*
* Each frame is also associated with a `Session` object which stores all
* persistent data. Persistent data can then be accessed via any `Frame` with
* the same ID since they share a `Session`.
*
*
* A `Frame` provides some basic methods, however, it can be cast to other
* frame types using the cast method which provides additional wrapper
* functions. An example is `ftl::rgbd::Frame`.
*
*
* @see https://gitlab.utu.fi/nicolas.pope/ftl/-/wikis/Design/Frames
*/
class Frame {
......@@ -330,7 +330,7 @@ class Frame {
* channel does not exist or if the template type does not match the content
* then it throws an exception. The data can either be within this frame,
* or if not in the frame then it checks the persistent store.
*
*
* The data may internally still be encoded and will only be decoded on the
* first call to `get`. It is therefore strongly advised that any initial
* calls to `get` are not concurrent as it will not be thread-safe.
......@@ -431,7 +431,7 @@ class Frame {
/**
* Create a change but with encoded data provided. This allows for both
* lazy decode and for subsequent data forwarding without encoding.
*
*
* Currently unused.
*/
template <typename T>
......@@ -441,7 +441,7 @@ class Frame {
* Create a channel, mark with the given change type and provided encoded
* data. Does not decode the data as it does not know the actually data
* type of this channel at this time.
*
*
* To be used by `receiver`.
* @see ftl::stream::Receiver
*/
......@@ -517,7 +517,7 @@ class Frame {
* do generate a change event but do no subsequently generate a flush event
* as they are considered completed changes. This prevents loops whilst
* ensuring everyone has a copy of the change.
*
*
* @see changeType
*/
inline ftl::Handle onFlush(const std::function<bool(Frame&,ftl::codecs::Channel)> &cb);
......
......@@ -268,25 +268,29 @@ void Frame::store() {
if (!parent_) return;
UNIQUE_LOCK(parent_->mutex(), lk);
{
UNIQUE_LOCK(parent_->mutex(), lk);
for (auto c : changed_) {
if (ftl::data::isPersistent(c.first) && hasOwn(c.first)) {
auto &d = data_[c.first];
auto &pd = parent_->data_[c.first];
pd.data = std::move(d.data);
pd.encoded = std::move(d.encoded);
//if (d.status == ChannelStatus::ENCODED) LOG(INFO) << "STORE ENCODED: " << (int)c.first;
pd.status = ChannelStatus::VALID;
//data_.erase(c.first);
d.status = ChannelStatus::INVALID;
}
for (auto c : changed_) {
if (ftl::data::isPersistent(c.first) && hasOwn(c.first)) {
auto &d = data_[c.first];
auto &pd = parent_->data_[c.first];
pd.data = std::move(d.data);
pd.encoded = std::move(d.encoded);
//if (d.status == ChannelStatus::ENCODED) LOG(INFO) << "STORE ENCODED: " << (int)c.first;
pd.status = ChannelStatus::VALID;
//data_.erase(c.first);
d.status = ChannelStatus::INVALID;
uint64_t sig = (uint64_t(id()) << 32) + static_cast<unsigned int>(c.first);
const auto &i = parent_->change_channel_.find(sig);
if (i != parent_->change_channel_.end()) i->second.trigger(*this, c.first);
}
}
for (auto c : changed_) {
parent_->change_.trigger(*this, c.first);
uint64_t sig = (uint64_t(id()) << 32) + static_cast<unsigned int>(c.first);
const auto &i = parent_->change_channel_.find(sig);
if (i != parent_->change_channel_.end()) i->second.trigger(*this, c.first);
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment