diff --git a/realm_delegate.hpp b/realm_delegate.hpp index 0941b2dc..0d9e9dfe 100644 --- a/realm_delegate.hpp +++ b/realm_delegate.hpp @@ -25,24 +25,106 @@ #include namespace realm { +// RealmDelegate is the extension point for adding binding-specific behavior to +// a SharedRealm. It can be used to store additonal data associated with the +// Realm which is needed by the binding, and there are several methods which +// can be overridden to receive notifications of state changes within the Realm. +// +// A simple delegate implementation which lets the user register functions to be +// called on refresh could look like the following: +// +// class DelegateImplementation : public RealmDelegate { +// public: +// // A token returned from add_notification that can be used to remove the +// // notification later +// struct token : private std::list>::iterator { +// token(std::list>::iterator it) : std::list>::iterator(it) { } +// friend class DelegateImplementation; +// }; +// +// token add_notification(std::function func) +// { +// m_registered_notifications.push_back(std::move(func)); +// return token(std::prev(m_registered_notifications.end())); +// } +// +// void remove_notification(token entry) +// { +// m_registered_notifications.erase(entry); +// } +// +// // Override the did_change method to call each registered notification +// void did_change(std::vector const&, std::vector const&) override +// { +// // Loop oddly so that unregistering a notification from within the +// // registered function works +// for (auto it = m_registered_notifications.begin(); it != m_registered_notifications.end(); ) { +// (*it++)(); +// } +// } +// +// private: +// std::list> m_registered_notifications; +// }; class RealmDelegate { public: virtual ~RealmDelegate() = default; + // Called by the Realm when a write transaction is committed to the file by + // a different Realm instance (possibly in a different process) + virtual void changes_available() { } + + struct ObserverState; + + // Override this function if you want to recieve detailed information about + // external changes to a specific set of objects. + // This is called before each operation which may advance the read + // transaction to include + // ObserverStates for each row for which detailed change information is + // desired. + virtual std::vector get_observed_rows() { return {}; } + + // Called immediately before the read transaction is advanced if detailed + // change information was requested (by returning a non-empty array from + // get_observed_rows()). + // The observers vector is the vector returned by get_observed_row(), + // updated with change information. The invalidated vector is a list of the + // `info` fields of observed rows which will be deleted. + virtual void will_change(std::vector const& observers, + std::vector const& invalidated); + + // Called immediately after the read transaction version is advanced. Unlike + // will_change(), this is called even if detailed change information was not + // requested or if the Realm is not actually in a read transactuib, although + // both vectors will be empty in that case. + virtual void did_change(std::vector const& observers, + std::vector const& invalidated); + // Change information for a single field of a row struct ColumnInfo { + // Did this column change? bool changed = false; + // For LinkList columns, what kind of change occurred? + // Always None for other column types enum class Kind { - None, - Set, - Insert, - Remove, - SetAll + None, // No change + Set, // The entries at `indices` were assigned to + Insert, // New values were inserted at each of the indices given + Remove, // Values were removed at each of the indices given + SetAll // The entire LinkList has been replaced with a new set of values } kind = Kind::None; + // The indices where things happened for Set, Insert and Remove + // Not used for None and SetAll IndexSet indices; }; // Information about an observed row in a table + // + // Each object which needs detailed change information should have an + // ObserverState entry in the vector returned from get_observed_rows(), with + // the initial table and row indexes set (and optionally the info field). + // The Realm parses the transaction log, and populates the `changes` vector + // in each ObserverState with information about what changes were made. struct ObserverState { // Initial table and row which is observed // May be updated by row insertions and removals @@ -58,35 +140,15 @@ public: std::vector changes; // Simple lexographic ordering - friend bool operator<(ObserverState const& lft, ObserverState const& rgt) { + friend bool operator<(ObserverState const& lft, ObserverState const& rgt) + { return std::tie(lft.table_ndx, lft.row_ndx) < std::tie(rgt.table_ndx, rgt.row_ndx); } }; - - // There are now new versions available for the Realm, but it has not - // had its read version advanced - virtual void changes_available() = 0; - - // Called before changing the read transaction. Should return a list of - // ObserverStates for each row for which detailed change information is - // desired. - virtual std::vector get_observed_rows() = 0; - - // The Realm's read version will change - // Only called if get_observed_row() returned a non-empty array. - // observers is the vector returned from get_observed_rows() - // invalidated is the `info` pointers for each observed object which was deleted - virtual void will_change(std::vector const& observers, - std::vector const& invalidated) = 0; - - // The Realm's read version has changed - // observers is the vector returned from get_observed_rows() - // invalidated is the `info` pointers for each observed object which was deleted - // Is called with empty change information following a local commit or if - // the Realm isn't in a read transaction yet - virtual void did_change(std::vector const& observers, - std::vector const& invalidated) = 0; }; + +inline void RealmDelegate::will_change(std::vector const&, std::vector const&) { } +inline void RealmDelegate::did_change(std::vector const&, std::vector const&) { } } // namespace realm #endif /* REALM_DELEGATE_HPP */