From 20daa3c4285c91dfcd35361f6550f80315e008a5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 5 Feb 2013 15:41:56 +0200 Subject: Add support for updating callback registration --- odb/transaction.cxx | 105 ++++++++++++++++++++++++++++++++-------------------- odb/transaction.hxx | 9 +++++ 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/odb/transaction.cxx b/odb/transaction.cxx index 197fc63..508d1aa 100644 --- a/odb/transaction.cxx +++ b/odb/transaction.cxx @@ -226,74 +226,99 @@ namespace odb s->state = state; } - void transaction:: - unregister (void* key) + size_t transaction:: + find (void* key) { - // Note that it is ok for this function not to find the key. - // if (callback_count_ == 0) - return; + return 0; size_t stack_count; - // See if this is the last slot registered. This will be a fast path - // if things are going to be unregistered from destructors. + // See if this is the last slot registered. This will be a fast path if, + // for example, things are going to be unregistered from destructors. // if (callback_count_ <= stack_callback_count) { if (stack_callbacks_[callback_count_ - 1].key == key) - { - callback_count_--; - return; - } + return callback_count_ - 1; stack_count = callback_count_; } else { if (dyn_callbacks_.back ().key == key) - { - dyn_callbacks_.pop_back (); - callback_count_--; - return; - } + return callback_count_ - 1; stack_count = stack_callback_count; } - size_t dyn_count (callback_count_ - stack_count); - // Otherwise do a linear search. // for (size_t i (0); i < stack_count; ++i) + if (stack_callbacks_[i].key == key) + return i; + + for (size_t i (0), dyn_count (callback_count_ - stack_count); + i < dyn_count; ++i) + if (dyn_callbacks_[i].key == key) + return i + stack_callback_count; + + return callback_count_; + } + + void transaction:: + unregister (void* key) + { + size_t i (find (key)); + + // It is ok for this function not to find the key. + // + if (i == callback_count_) + return; + + // See if this is the last slot registered. + // + if (i == callback_count_ - 1) { - callback_data& d (stack_callbacks_[i]); - if (d.key == key) - { - // Add to the free list. - // - d.event = 0; - d.key = reinterpret_cast (free_callback_); - free_callback_ = i; - return; - } - } + if (i >= stack_callback_count) + dyn_callbacks_.pop_back (); - for (size_t i (0); i < dyn_count; ++i) + callback_count_--; + } + else { - callback_data& d (dyn_callbacks_[i]); - if (d.key == key) - { - // Add to the free list. - // - d.event = 0; - d.key = reinterpret_cast (free_callback_); - free_callback_ = stack_callback_count + i; - return; - } + callback_data& d ( + i < stack_callback_count + ? stack_callbacks_[i] + : dyn_callbacks_[i - stack_callback_count]); + + // Add to the free list. + // + d.event = 0; + d.key = reinterpret_cast (free_callback_); + free_callback_ = i; } } + void transaction:: + update (void* key, unsigned long long data, transaction** state) + { + size_t i (find (key)); + + // It is ok for this function not to find the key. + // + if (i == callback_count_) + return; + + callback_data& d ( + i < stack_callback_count + ? stack_callbacks_[i] + : dyn_callbacks_[i - stack_callback_count]); + + d.data = data; + d.state = state; + } + // // transaction_impl // diff --git a/odb/transaction.hxx b/odb/transaction.hxx index 1f7b866..e035661 100644 --- a/odb/transaction.hxx +++ b/odb/transaction.hxx @@ -136,6 +136,12 @@ namespace odb void unregister (void* key); + // Update the data and state values for a callback. Note that just + // like unregister(), this is a potentially slow operation. + // + void + update (void* key, unsigned long long data, transaction** state = 0); + public: transaction_impl& implementation (); @@ -149,6 +155,9 @@ namespace odb protected: friend struct rollback_guard; + std::size_t + find (void* key); + void call (unsigned short event); -- cgit v1.1