improve class observable
This commit is contained in:
parent
5a4e247564
commit
32a125a767
|
@ -62,20 +62,39 @@ namespace UTIL {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OBSERVABLE_BASE::IMPL::enter_iteration()
|
||||||
|
{
|
||||||
|
++iteration_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBSERVABLE_BASE::IMPL::leave_iteration()
|
||||||
|
{
|
||||||
|
--iteration_count_;
|
||||||
|
if(iteration_count_ == 0) {
|
||||||
|
collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OBSERVABLE_BASE::IMPL::is_iterating() const
|
||||||
|
{
|
||||||
|
return iteration_count_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBSERVABLE_BASE::IMPL::add_observer( void* observer )
|
||||||
|
{
|
||||||
|
assert( !is_iterating() );
|
||||||
|
observers_.push_back( observer );
|
||||||
|
}
|
||||||
|
|
||||||
void OBSERVABLE_BASE::IMPL::remove_observer( void* observer )
|
void OBSERVABLE_BASE::IMPL::remove_observer( void* observer )
|
||||||
{
|
{
|
||||||
if(iteration_count_) {
|
auto it = std::find( observers_.begin(), observers_.end(), observer );
|
||||||
for(auto*& ptr : observers_) {
|
|
||||||
if(ptr == observer) {
|
if(is_iterating()) {
|
||||||
ptr = nullptr;
|
*it = nullptr;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
collect();
|
observers_.erase( it );
|
||||||
if(observers_.empty() && owned_by_) {
|
|
||||||
owned_by_->on_observers_empty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +141,7 @@ namespace UTIL {
|
||||||
{
|
{
|
||||||
if(token_) {
|
if(token_) {
|
||||||
token_->remove_observer( observer_ );
|
token_->remove_observer( observer_ );
|
||||||
|
token_.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,19 +160,6 @@ namespace UTIL {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t OBSERVABLE_BASE::size() const {
|
|
||||||
if(impl_) {
|
|
||||||
return impl_->observers_.size();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBSERVABLE_BASE::remove_observer( void* observer ) {
|
|
||||||
assert( impl_ );
|
|
||||||
impl_->remove_observer( observer );
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBSERVABLE_BASE::allocate_impl() {
|
void OBSERVABLE_BASE::allocate_impl() {
|
||||||
if(!impl_) {
|
if(!impl_) {
|
||||||
|
@ -174,26 +181,47 @@ namespace UTIL {
|
||||||
impl_.reset();
|
impl_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<OBSERVABLE_BASE::IMPL> OBSERVABLE_BASE::get_shared_impl()
|
||||||
|
{
|
||||||
|
allocate_shared_impl();
|
||||||
|
return impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBSERVABLE_BASE::add_observer( void* observer ) {
|
||||||
|
allocate_impl();
|
||||||
|
impl_->add_observer( observer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBSERVABLE_BASE::remove_observer( void* observer ) {
|
||||||
|
assert( impl_ );
|
||||||
|
impl_->remove_observer( observer );
|
||||||
|
}
|
||||||
|
|
||||||
void OBSERVABLE_BASE::enter_iteration() {
|
void OBSERVABLE_BASE::enter_iteration() {
|
||||||
if(impl_) {
|
if(impl_) {
|
||||||
++impl_->iteration_count_;
|
impl_->enter_iteration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBSERVABLE_BASE::leave_iteration() {
|
void OBSERVABLE_BASE::leave_iteration() {
|
||||||
if(impl_) {
|
if(impl_) {
|
||||||
--impl_->iteration_count_;
|
impl_->leave_iteration();
|
||||||
if(impl_->iteration_count_ == 0) {
|
|
||||||
if(!impl_->is_shared() && impl_.use_count() == 1) {
|
if( !impl_->is_iterating() && !impl_->is_shared() && impl_.use_count() == 1 ) {
|
||||||
impl_.reset();
|
impl_.reset();
|
||||||
}
|
|
||||||
else {
|
|
||||||
impl_->collect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t OBSERVABLE_BASE::size() const {
|
||||||
|
if(impl_) {
|
||||||
|
return impl_->observers_.size();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OBSERVABLE_BASE::on_observers_empty()
|
void OBSERVABLE_BASE::on_observers_empty()
|
||||||
{
|
{
|
||||||
// called by an impl that is owned by this, ie. it is a non-shared impl
|
// called by an impl that is owned by this, ie. it is a non-shared impl
|
||||||
|
@ -201,16 +229,7 @@ namespace UTIL {
|
||||||
deallocate_impl();
|
deallocate_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<OBSERVABLE_BASE::IMPL> OBSERVABLE_BASE::get_shared_impl()
|
|
||||||
{
|
|
||||||
allocate_shared_impl();
|
|
||||||
return impl_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBSERVABLE_BASE::add_observer( void* observer ) {
|
|
||||||
allocate_impl();
|
|
||||||
impl_->observers_.push_back( observer );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,15 @@ namespace UTIL {
|
||||||
void set_shared();
|
void set_shared();
|
||||||
~IMPL();
|
~IMPL();
|
||||||
|
|
||||||
|
void add_observer( void* observer );
|
||||||
void remove_observer( void* observer );
|
void remove_observer( void* observer );
|
||||||
void collect();
|
void collect();
|
||||||
|
|
||||||
|
bool is_iterating() const;
|
||||||
|
|
||||||
|
void enter_iteration();
|
||||||
|
void leave_iteration();
|
||||||
|
|
||||||
std::vector<void*> observers_;
|
std::vector<void*> observers_;
|
||||||
unsigned int iteration_count_;
|
unsigned int iteration_count_;
|
||||||
OBSERVABLE_BASE* owned_by_;
|
OBSERVABLE_BASE* owned_by_;
|
||||||
|
@ -147,7 +153,7 @@ namespace UTIL {
|
||||||
*/
|
*/
|
||||||
void SubscribeUnmanaged( ObserverInterface* aObserver )
|
void SubscribeUnmanaged( ObserverInterface* aObserver )
|
||||||
{
|
{
|
||||||
return OBSERVABLE_BASE::add_observer_unmanaged( static_cast<void*>(aObserver) );
|
OBSERVABLE_BASE::add_observer( static_cast<void*>(aObserver) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue