patterncppMinor
A reader and its associated writer for disjoint value access
Viewed 0 times
writervalueitsforassociateddisjointandaccessreader
Problem
While extending the functionality of my
Since that other question is already very long, I've decided to post this question for a review that focuses on these simple classes.
Reader
reader.h
```
#ifndef READER_H
#define READER_H
#include
#include
template class writer;
template
class reader
{
public:
using value_type = T;
/**
* @brief sets the associated writer's pointer to nullptr
*/
~reader() noexcept( std::is_nothrow_destructible::value )
{
writer_->value_ = nullptr;
}
/**
* @brief takes ownership of the contained value of the argument reader as
* if by move construction; associates the writer associated with the argument
* reader with this reader.
*/
reader( reader&& rhs )
noexcept( std::is_nothrow_move_constructible::value )
: value_{ std::move( rhs.value_ ) }
, writer_{ rhs.writer_ }
{
rhs.writer_->value_ = &value_;
}
/**
* @brief takes ownership of the contained value of the argument reader as
* if by move assignment; associates the writer associated with the argument
* reader with this reader.
*/
reader& operator=( reader&& rhs )
noexcept( std::is_nothrow_move_assignable::value )
{
writer_ = rhs.writer_;
value_ = std::move( rhs.value_ );
rhs.writer_->value_ = &value_;
}
reader( reader const& ) = delete;
reader& operator=( reader const& ) = delete;
/**
* @brief access the contained value
*/
polymorphic_callable<> type, I designed a way to obtain a result through a reader type that is set by a writer type; this is very similar to what std::future<> and std::promise<> do, but in a non-multi-threaded way.Since that other question is already very long, I've decided to post this question for a review that focuses on these simple classes.
Reader
reader<> semantics:- It can only read from its contained value.
- It is a move-only type that can only be created by a
writer<>instance'screate_reader()member function.
- On destruction, its associated
writer<>'s writing pointer is set tonullptr.
reader.h
```
#ifndef READER_H
#define READER_H
#include
#include
template class writer;
template
class reader
{
public:
using value_type = T;
/**
* @brief sets the associated writer's pointer to nullptr
*/
~reader() noexcept( std::is_nothrow_destructible::value )
{
writer_->value_ = nullptr;
}
/**
* @brief takes ownership of the contained value of the argument reader as
* if by move construction; associates the writer associated with the argument
* reader with this reader.
*/
reader( reader&& rhs )
noexcept( std::is_nothrow_move_constructible::value )
: value_{ std::move( rhs.value_ ) }
, writer_{ rhs.writer_ }
{
rhs.writer_->value_ = &value_;
}
/**
* @brief takes ownership of the contained value of the argument reader as
* if by move assignment; associates the writer associated with the argument
* reader with this reader.
*/
reader& operator=( reader&& rhs )
noexcept( std::is_nothrow_move_assignable::value )
{
writer_ = rhs.writer_;
value_ = std::move( rhs.value_ );
rhs.writer_->value_ = &value_;
}
reader( reader const& ) = delete;
reader& operator=( reader const& ) = delete;
/**
* @brief access the contained value
*/
Solution
Easy of use:
You could make implicit conversion to bool for
Since classes has explicit names, you could write
Matter to think about:
The code uses circular references. I know that it greatly simplifies the implementation, but probably there is a better solution. I think that the problem leads to creation of raw memory class, which would be supplied into the
You could make implicit conversion to bool for
writer<> class, so it would be less cumbersome to use it. On the other hand, those who are not familiar with the internals might be surprised during their first use.Since classes has explicit names, you could write
operator(), since it is explicit that invoking it on reader<> object will perform read, and invoking it with parameter on writer<> object will perform writing. Matter to think about:
The code uses circular references. I know that it greatly simplifies the implementation, but probably there is a better solution. I think that the problem leads to creation of raw memory class, which would be supplied into the
polymorphic_callable<>. std::optional<> would be great idea too. When std::optional<> object will evaluate to true, it will mean that the function has been called and it properly finished execution. You could provide your own until C++17, since it is pretty trivial to write one.Context
StackExchange Code Review Q#140594, answer score: 2
Revisions (0)
No revisions yet.