//! @file async-Dispatch-example.cpp
//! @brief ZeroMQ / async::dispatch_t example.
//! @author Oliver 'kfs1' Smith <oliver@kfs.org>

#include "async-worker.h"		// The Asyc:: classes.
#include <OpenThreads/Thread>	// For thread sleep.
#include <string>				// For std::string.
#include <stdio.h>				// For printf

//! @class DBOffload

//! Mock class that demonstrates how you might
//! offload writes to a database.

class DBOffload : public async::dispatch_t
{
	//! Constructor
	//! @param[in]	query	Query String to execute.
	//! Takes a copy of the query string for itself.
public: DBOffload(const std::string& query) : dispatch_t(), m_query(query) {}

	//! Execution function.
	//! Describes the work to be executed by the worker.
	//! Note constness.
public:	virtual void Work()
		{
		/*
			In practice you would open the database connection
			here and connect to it, something like:

			MYSQL* conn = msql_connect(database);
			mysql_real_query(conn, query.c_str(), query.length());
		
			For demonstration purposes, I'm just going to print
			the query while the caller sleeps.
		*/

			// Work-simulation.
			OpenThreads::Thread::microSleep(5000) ;
			printf("query being done while main thread does something else (sleeps in this case)\n") ;
			printf("%s\n", m_query.c_str()) ;
			OpenThreads::Thread::microSleep(5000) ;
			printf("Done, this worker will now self-destruct\n") ;
		}

	//! Storage for the query.
private: std::string m_query ;
} ;

int main(int argc, const char* const argv[])
{
	// Method 1.
	async::Queue(new DBOffload("INSERT INTO `user` (`beverage`, `quantity`) VALUES ('coffee', 'significant')")) ;

	// Method 2.
	DBOffload* work = new DBOffload("DELETE FROM `user` WHERE `beverage` = 'nasty tasting'") ;
	work->Queue() ;

	// DO NOT DO THE FOLLOWING because FireAndForget workers 'delete' themselves.
	/*
		DBOffload work("SELECT crash FROM application") ;
		work.Queue() ;
	*/

	// Now lets simulate doing some other work while that goes on in the background.

	printf("[originating thread is ''busy'' doing other stuff now]\n") ;
	OpenThreads::Thread::microSleep(1 * 1000 * 1000) ;	// Wait a second.
	printf("[originating thread has finished. is it over now?]\n") ;

	return 0 ;
}

