stasher::create_manage_object<classptr>(): call a functor after deserializing an object

The following example shows the current contents of the inventory object, and shows the updated contents any time that setinventory, executes on the same node or any other node in the cluster, and updates the contents of the inventory object. Pass the name of the object as a parameter to showinventory:

#include <stasher/client.H>
#include <stasher/manager.H>

#include "inventory.H"

void update(const inventoryptr &ptr, bool initial);

void showinventory(int argc, char **argv)
{
	if (argc < 2)
		return;

	auto client=stasher::client::base::connect();
	auto manager=stasher::manager::create();

	std::cout << "Showing current inventory, press Enter to stop"
		  << std::endl;

	x::ref<x::obj> mcguffin=manager->
		manage_object(client, argv[1],
			      stasher::create_managed_object<inventoryptr>
			      ([](const inventoryptr &ptr, bool initial)
		{
			update(std::move(ptr), initial);
		},
			       [](stasher::req_stat_t status)
		{
			std::cout << "Connection update: "
			<< x::tostring(status) << std::endl;
		}));

	std::string dummy;

	std::getline(std::cin, dummy);
}

void update(const inventoryptr &ptr, bool initial)
{
	std::cout << (initial ? "Current inventory:":"Updated inventory:")
		  << std::endl;

	if (ptr.null())
	{
		std::cout << "    (none)" << std::endl;
	}
	else
	{
		std::cout << "    "
			  << std::setw(30) << std::left
			  << "Item"
			  << "   "
			  << std::setw(8) << std::right
			  << "Count" << std::setw(0)
			  << std::endl;

		std::cout << "    "
			  << std::setfill('-') << std::setw(30)
			  << ""
			  << "   "
			  << std::setw(8)
			  << "" << std::setw(0) << std::setfill(' ')
			  << std::endl;

		for (auto &item:ptr->stock)
		{
			std::cout << "    "
				  << std::setw(30) << std::left
				  << item.first
				  << "   "
				  << std::setw(8) << std::right
				  << item.second << std::setw(0)
				  << std::endl;
		}
		std::cout << std::setw(75) << std::setfill('=') << ""
			  << std::setw(0) << std::setfill(' ') << std::endl;
	}

}

int main(int argc, char **argv)
{
	try {
		showinventory(argc, argv);
	} catch (const x::exception &e)
	{
		std::cerr << e << std::endl;
		return 1;
	}
	return 0;
}

stasher::create_manage_object()'s classptr template parameter is an x::ptr to an object that meets the requirements in the section called “Requirements”. stasher::create_manage_object() returns a stasher::managedobject that can be passed as the third parameter to stasher::manager->manage_object().

The first parameter to stasher::create_manage_object() is a functor that takes two parameters, a classptr and a bool. stasher::create_manage_object<>() instantiates a stasher::managedobject whose updated() invokes the functor passing it a classptr to an instance of the template class constructed with the forwarded x::uuid and file descriptor parameters, and whose removed() invokes the functor with a nullptr classptr.

In either case, the second bool parameter to the functor is true if this is the first object that's retrieved from the repository after a connection or a reconnection, indicating the initial value of the object; and false for subsequent invocations.

The second parameter to stasher::create_manage_object<>() is a functor that takes a stasher::req_stat_t parameter, which is forwarded from the managed object's connection_update() callback, and works similarly to the connection_update() in other managed objects and subscriptions.

The second functor parameter is optional, and may be omitted if its functionality is not needed.

To summarize:

The functors have certain limitations, see the section called “What asynchronous C++ API methods can and cannot do” for more information; with the addition that exceptions thrown by the functors get caught, and logged, before returning.